[patch 2/8] powerpc: systemsim block device driver

Olof Johansson olof at lixom.net
Sat Jan 14 13:54:52 EST 2006


On Fri, Jan 13, 2006 at 01:30:35PM -0500, Arnd Bergmann wrote:
> The block device driver for systemsim is currently
> required for running on the Cell systemsim port, which
> does not simulate any other block devices.

Maybe I'm just missing it, but I'm not seeing where the _init function
is detecting the presence of the driver (i.e. the environment) without
doing callthru() calls. There should be a way to detect the presence of
it before you start executing random instructions (which is what the
callthru is, right?)

Also, do you want to keep the Mambo naming in there, or move over to
systemsim?

> 
> From: Eric Van Hensbergen <ericvh at gmail.com>
> Signed-off-by: Arnd Bergmann <arndb at de.ibm.com>
> 
> 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 <file:Documentation/initrd.txt>
>  	  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 <ericvh at gmail.com>
> + *
> + *    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 <IBM Austin Research Lab>
> + *
> + * 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 <linux/major.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/sched.h>
> +#include <linux/fs.h>
> +#include <linux/stat.h>
> +#include <linux/errno.h>
> +#include <linux/file.h>
> +#include <linux/ioctl.h>
> +#include <linux/blkdev.h>
> +#include <net/sock.h>
> +
> +#include <asm/systemsim.h>
> +
> +#include <linux/devfs_fs_kernel.h>

devfs? really? Don't show this to Greg K-H. :-)

> +
> +#include <asm/uaccess.h>
> +#include <asm/types.h>
> +
> +#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;
whitespace
> +};
> +
> +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)

CanWeGetRidOfTheSillyCaps?

> +{
> +	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");
> 
> --
> 
> _______________________________________________
> Linuxppc64-dev mailing list
> Linuxppc64-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc64-dev



More information about the Linuxppc64-dev mailing list