/*
 * 5799-WZQ (C) COPYRIGHT = NONE
 * LICENSED MATERIALS - PROPERTY OF IBM
 */
/* $Header:bdev_vnodeops.c 12.0$ */
/* $ACIS:bdev_vnodeops.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/specfs/RCS/bdev_vnodeops.c,v $ */

#ifndef lint
static char *rcsid = "$Header:bdev_vnodeops.c 12.0$";
#endif

/* @(#)bdev_vnodeops.c	1.3 87/06/30 3.2/4.3NFSSRC */
#ifndef lint
static  char sccsid[] = "@(#)bdev_vnodeops.c 1.1 86/09/25";
#endif

/*
 * Copyright (c) 1986 by Sun Microsystems, Inc.
 */

#ifdef VFS
#include "param.h"
#include "systm.h"
#include "dir.h"
#include "user.h"
#include "conf.h"
#include "buf.h"
#include "vfs.h"
#include "vnode.h"
#include "trace.h"


/*
 * Convert a block dev into a vnode pointer suitable for bio.
 */

struct dev_vnode {
	struct vnode dv_vnode;
	struct dev_vnode *dv_link;
} *dev_vnode_headp;

bdev_badop()
{

	panic("bdev_badop");
}

/*ARGSUSED*/
int
bdev_open(vpp, flag, cred)
	struct vnode **vpp;
	int flag;
	struct ucred *cred;
{

	return ((*bdevsw[major((*vpp)->v_rdev)].d_open)((*vpp)->v_rdev, flag));
}

/*ARGSUSED*/
int
bdev_close(vp, flag, cred)
	struct vnode *vp;
	int flag;
	struct ucred *cred;
{

	/*
	 * On last close of a block device (that isn't mounted)
	 * we must invalidate any in core blocks, so that
	 * we can, for instance, change floppy disks.
	 */
#ifdef ibm032
	trace(TR_BCLOSE, pack(vp->v_rdev, 0x8000|flag), vp);
#endif /* ibm032 */
	bflush(vp);
	binval(vp);
	return ((*bdevsw[major(vp->v_rdev)].d_close)(vp->v_rdev, flag));
}

/*
 * For now, the only value we actually return is size.
 */
/*ARGSUSED*/
int
bdev_getattr(vp, vap, cred)
	struct vnode *vp;
	register struct vattr *vap;
	struct ucred *cred;
{
	int (*size)();

	bzero((caddr_t) vap, sizeof (struct vattr));
	size = bdevsw[major(vp->v_rdev)].d_psize;
	if (size) {
		vap->va_size = (*size)(vp->v_rdev) * DEV_BSIZE;
	}
	return (0);
}

/*ARGSUSED*/
int
bdev_inactive(vp)
	struct vnode *vp;
{

	/* could free the vnode here */
	return (0);
}

int
bdev_strategy(bp)
	struct buf *bp;
{

	(*bdevsw[major(bp->b_vp->v_rdev)].d_strategy)(bp);
	return (0);
}

int
devtovp_minphys(bp)
	struct buf *bp;
{

	(*bdevsw[major(bp->b_dev)].d_minphys)(bp);
	return(0);
}

struct vnodeops dev_vnode_ops = {
	bdev_open,
	bdev_close,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_getattr,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_inactive,
	bdev_badop,
	bdev_strategy,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	bdev_badop,
	devtovp_minphys
};

/*
 * Convert a block device into a special purpose vnode for bio
 */
struct vnode *
bdevvp(dev)
	dev_t dev;
{
	register struct dev_vnode *dvp;
	register struct dev_vnode *endvp;

	endvp = (struct dev_vnode *)0;
	for (dvp = dev_vnode_headp; dvp; dvp = dvp->dv_link) {
		if (dvp->dv_vnode.v_rdev == dev) {
			VN_HOLD(&dvp->dv_vnode);
#ifdef ibm032
			trace(TR_BDEVVP, &dvp->dv_vnode, dev);/* hit - found old one */
#endif /* ibm032 */
			return (&dvp->dv_vnode);
		}
		endvp = dvp;
	}
	dvp = (struct dev_vnode *)
		kmem_alloc((u_int)sizeof (struct dev_vnode));
	bzero((caddr_t)dvp, sizeof (struct dev_vnode));
	dvp->dv_vnode.v_count = 1;
	dvp->dv_vnode.v_op = &dev_vnode_ops;
	dvp->dv_vnode.v_rdev = dev;
	if (endvp != (struct dev_vnode *)0) {
		endvp->dv_link = dvp;
	} else {
		dev_vnode_headp = dvp;
	}
#ifdef ibm032
	trace(TR_BDEVVP, &dvp->dv_vnode, dev);/* miss - created new one */
#endif /* ibm032 */
	return (&dvp->dv_vnode);
}
#endif VFS
