version 1.73, 2001/08/05 11:20:13 |
version 1.73.2.3, 2001/10/01 12:44:10 |
|
|
#include <sys/lock.h> |
#include <sys/lock.h> |
#include <sys/queue.h> |
#include <sys/queue.h> |
|
|
|
#include <miscfs/specfs/specdev.h> |
|
|
#include <dev/ccdvar.h> |
#include <dev/ccdvar.h> |
|
|
#if defined(CCDDEBUG) && !defined(DEBUG) |
#if defined(CCDDEBUG) && !defined(DEBUG) |
Line 159 static int ccdlookup __P((char *, struct |
|
Line 161 static int ccdlookup __P((char *, struct |
|
static struct ccdbuf *ccdbuffer __P((struct ccd_softc *, struct buf *, |
static struct ccdbuf *ccdbuffer __P((struct ccd_softc *, struct buf *, |
daddr_t, caddr_t, long)); |
daddr_t, caddr_t, long)); |
static void ccdgetdefaultlabel __P((struct ccd_softc *, struct disklabel *)); |
static void ccdgetdefaultlabel __P((struct ccd_softc *, struct disklabel *)); |
static void ccdgetdisklabel __P((dev_t)); |
static void ccdgetdisklabel __P((struct vnode *)); |
static void ccdmakedisklabel __P((struct ccd_softc *)); |
static void ccdmakedisklabel __P((struct ccd_softc *)); |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
Line 279 ccdinit(cs, cpaths, vpp, p) |
|
Line 281 ccdinit(cs, cpaths, vpp, p) |
|
#endif |
#endif |
goto out; |
goto out; |
} |
} |
ci->ci_dev = va.va_rdev; |
|
|
|
/* |
/* |
* Get partition information for the component. |
* Get partition information for the component. |
Line 490 ccdinterleave(cs) |
|
Line 491 ccdinterleave(cs) |
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
ccdopen(dev, flags, fmt, p) |
ccdopen(devvp, flags, fmt, p) |
dev_t dev; |
struct vnode *devvp; |
int flags, fmt; |
int flags, fmt; |
struct proc *p; |
struct proc *p; |
{ |
{ |
int unit = ccdunit(dev); |
int unit; |
struct ccd_softc *cs; |
struct ccd_softc *cs; |
struct disklabel *lp; |
struct disklabel *lp; |
int error = 0, part, pmask; |
int error, part, pmask; |
|
dev_t rdev; |
|
|
|
rdev = vdev_rdev(devvp); |
|
cs = vdev_privdata(devvp); |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_FOLLOW) |
if (ccddebug & CCDB_FOLLOW) |
printf("ccdopen(0x%x, 0x%x)\n", dev, flags); |
printf("ccdopen(0x%x, 0x%x)\n", rdev, flags); |
#endif |
#endif |
|
|
|
unit = ccdunit(rdev); |
if (unit >= numccd) |
if (unit >= numccd) |
return (ENXIO); |
return (ENXIO); |
cs = &ccd_softc[unit]; |
cs = &ccd_softc[unit]; |
|
vdev_setprivdata(devvp, cs); |
|
|
if ((error = lockmgr(&cs->sc_lock, LK_EXCLUSIVE, NULL)) != 0) |
if ((error = lockmgr(&cs->sc_lock, LK_EXCLUSIVE, NULL)) != 0) |
return (error); |
return (error); |
|
|
lp = cs->sc_dkdev.dk_label; |
lp = cs->sc_dkdev.dk_label; |
|
|
part = DISKPART(dev); |
part = DISKPART(rdev); |
pmask = (1 << part); |
pmask = (1 << part); |
|
|
/* |
/* |
Line 522 ccdopen(dev, flags, fmt, p) |
|
Line 530 ccdopen(dev, flags, fmt, p) |
|
* the in-core disklabel. |
* the in-core disklabel. |
*/ |
*/ |
if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0)) |
if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0)) |
ccdgetdisklabel(dev); |
ccdgetdisklabel(devvp); |
|
|
/* Check that the partition exists. */ |
/* Check that the partition exists. */ |
if (part != RAW_PART) { |
if (part != RAW_PART) { |
Line 554 ccdopen(dev, flags, fmt, p) |
|
Line 562 ccdopen(dev, flags, fmt, p) |
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
ccdclose(dev, flags, fmt, p) |
ccdclose(devvp, flags, fmt, p) |
dev_t dev; |
struct vnode *devvp; |
int flags, fmt; |
int flags, fmt; |
struct proc *p; |
struct proc *p; |
{ |
{ |
int unit = ccdunit(dev); |
|
struct ccd_softc *cs; |
struct ccd_softc *cs; |
int error = 0, part; |
dev_t rdev; |
|
int error, part; |
|
|
|
cs = vdev_privdata(devvp); |
|
rdev = vdev_rdev(devvp); |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_FOLLOW) |
if (ccddebug & CCDB_FOLLOW) |
printf("ccdclose(0x%x, 0x%x)\n", dev, flags); |
printf("ccdclose(0x%x, 0x%x)\n", rdev, flags); |
#endif |
#endif |
|
|
if (unit >= numccd) |
|
return (ENXIO); |
|
cs = &ccd_softc[unit]; |
|
|
|
if ((error = lockmgr(&cs->sc_lock, LK_EXCLUSIVE, NULL)) != 0) |
if ((error = lockmgr(&cs->sc_lock, LK_EXCLUSIVE, NULL)) != 0) |
return (error); |
return (error); |
|
|
part = DISKPART(dev); |
part = DISKPART(rdev); |
|
|
/* ...that much closer to allowing unconfiguration... */ |
/* ...that much closer to allowing unconfiguration... */ |
switch (fmt) { |
switch (fmt) { |
|
|
ccdstrategy(bp) |
ccdstrategy(bp) |
struct buf *bp; |
struct buf *bp; |
{ |
{ |
int unit = ccdunit(bp->b_dev); |
struct ccd_softc *cs; |
struct ccd_softc *cs = &ccd_softc[unit]; |
|
int s; |
int s; |
int wlabel; |
int wlabel; |
struct disklabel *lp; |
struct disklabel *lp; |
|
dev_t rdev; |
|
|
|
cs = vdev_privdata(bp->b_devvp); |
|
rdev = vdev_rdev(bp->b_devvp); |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_FOLLOW) |
if (ccddebug & CCDB_FOLLOW) |
printf("ccdstrategy(%p): unit %d\n", bp, unit); |
printf("ccdstrategy(%p): unit %d\n", bp, DISKUNIT(rdev)); |
#endif |
#endif |
if ((cs->sc_flags & CCDF_INITED) == 0) { |
if ((cs->sc_flags & CCDF_INITED) == 0) { |
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_FOLLOW) |
if (ccddebug & CCDB_FOLLOW) |
printf("ccdstrategy: unit %d: not inited\n", unit); |
printf("ccdstrategy: unit %d: not inited\n", |
|
DISKUNIT(rdev)); |
#endif |
#endif |
bp->b_error = ENXIO; |
bp->b_error = ENXIO; |
bp->b_flags |= B_ERROR; |
bp->b_flags |= B_ERROR; |
|
|
* error, the bounds check will flag that for us. |
* error, the bounds check will flag that for us. |
*/ |
*/ |
wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); |
wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); |
if (DISKPART(bp->b_dev) != RAW_PART) |
if (DISKPART(rdev) != RAW_PART && |
|
(bp->b_flags & B_DKLABEL) == 0) |
if (bounds_check_with_label(bp, lp, wlabel) <= 0) |
if (bounds_check_with_label(bp, lp, wlabel) <= 0) |
goto done; |
goto done; |
|
|
Line 657 ccdstart(cs, bp) |
|
Line 669 ccdstart(cs, bp) |
|
daddr_t bn; |
daddr_t bn; |
struct partition *pp; |
struct partition *pp; |
SIMPLEQ_HEAD(, ccdbuf) cbufq; |
SIMPLEQ_HEAD(, ccdbuf) cbufq; |
|
dev_t rdev; |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_FOLLOW) |
if (ccddebug & CCDB_FOLLOW) |
Line 666 ccdstart(cs, bp) |
|
Line 679 ccdstart(cs, bp) |
|
/* Instrumentation. */ |
/* Instrumentation. */ |
disk_busy(&cs->sc_dkdev); |
disk_busy(&cs->sc_dkdev); |
|
|
|
rdev = vdev_rdev(bp->b_devvp); |
|
|
/* |
/* |
* Translate the partition-relative block number to an absolute. |
* Translate the partition-relative block number to an absolute. |
*/ |
*/ |
bn = bp->b_blkno; |
bn = bp->b_blkno; |
if (DISKPART(bp->b_dev) != RAW_PART) { |
if (DISKPART(rdev) != RAW_PART && |
pp = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]; |
(bp->b_flags & B_DKLABEL) == 0) { |
|
pp = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(rdev)]; |
bn += pp->p_offset; |
bn += pp->p_offset; |
} |
} |
|
|
Line 786 ccdbuffer(cs, bp, bn, addr, bcount) |
|
Line 802 ccdbuffer(cs, bp, bn, addr, bcount) |
|
cbp->cb_buf.b_flags = bp->b_flags | B_CALL; |
cbp->cb_buf.b_flags = bp->b_flags | B_CALL; |
cbp->cb_buf.b_iodone = ccdiodone; |
cbp->cb_buf.b_iodone = ccdiodone; |
cbp->cb_buf.b_proc = bp->b_proc; |
cbp->cb_buf.b_proc = bp->b_proc; |
cbp->cb_buf.b_dev = ci->ci_dev; /* XXX */ |
cbp->cb_buf.b_devvp = ci->ci_vp; |
cbp->cb_buf.b_blkno = cbn + cboff; |
cbp->cb_buf.b_blkno = cbn + cboff; |
cbp->cb_buf.b_data = addr; |
cbp->cb_buf.b_data = addr; |
cbp->cb_buf.b_vp = ci->ci_vp; |
cbp->cb_buf.b_vp = ci->ci_vp; |
Line 807 ccdbuffer(cs, bp, bn, addr, bcount) |
|
Line 823 ccdbuffer(cs, bp, bn, addr, bcount) |
|
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_IO) |
if (ccddebug & CCDB_IO) |
printf(" dev 0x%x(u%lu): cbp %p bn %d addr %p bcnt %ld\n", |
printf(" dev 0x%x(u%lu): cbp %p bn %d addr %p bcnt %ld\n", |
ci->ci_dev, (unsigned long) (ci-cs->sc_cinfo), cbp, |
ci->ci_vp->v_rdev, (unsigned long) (ci-cs->sc_cinfo), cbp, |
cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, |
cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, |
cbp->cb_buf.b_bcount); |
cbp->cb_buf.b_bcount); |
#endif |
#endif |
|
|
printf("ccdiodone: bp %p bcount %ld resid %ld\n", |
printf("ccdiodone: bp %p bcount %ld resid %ld\n", |
bp, bp->b_bcount, bp->b_resid); |
bp, bp->b_bcount, bp->b_resid); |
printf(" dev 0x%x(u%d), cbp %p bn %d addr %p bcnt %ld\n", |
printf(" dev 0x%x(u%d), cbp %p bn %d addr %p bcnt %ld\n", |
cbp->cb_buf.b_dev, cbp->cb_comp, cbp, |
cbp->cb_buf.b_devvp->v_rdev, cbp->cb_comp, cbp, |
cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, |
cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, |
cbp->cb_buf.b_bcount); |
cbp->cb_buf.b_bcount); |
} |
} |
|
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
ccdread(dev, uio, flags) |
ccdread(devvp, uio, flags) |
dev_t dev; |
struct vnode *devvp; |
struct uio *uio; |
struct uio *uio; |
int flags; |
int flags; |
{ |
{ |
int unit = ccdunit(dev); |
|
struct ccd_softc *cs; |
struct ccd_softc *cs; |
|
|
|
cs = vdev_privdata(devvp); |
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_FOLLOW) |
if (ccddebug & CCDB_FOLLOW) |
printf("ccdread(0x%x, %p)\n", dev, uio); |
printf("ccdread(0x%x, %p)\n", vdev_rdev(devvp), uio); |
#endif |
#endif |
if (unit >= numccd) |
|
return (ENXIO); |
|
cs = &ccd_softc[unit]; |
|
|
|
if ((cs->sc_flags & CCDF_INITED) == 0) |
if ((cs->sc_flags & CCDF_INITED) == 0) |
return (ENXIO); |
return (ENXIO); |
|
|
Line 910 ccdread(dev, uio, flags) |
|
Line 922 ccdread(dev, uio, flags) |
|
* in particular, for raw I/O. Underlying devices might have some |
* in particular, for raw I/O. Underlying devices might have some |
* non-obvious limits, because of the copy to user-space. |
* non-obvious limits, because of the copy to user-space. |
*/ |
*/ |
return (physio(ccdstrategy, NULL, dev, B_READ, minphys, uio)); |
return (physio(ccdstrategy, NULL, devvp, B_READ, minphys, uio)); |
} |
} |
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
int |
int |
ccdwrite(dev, uio, flags) |
ccdwrite(devvp, uio, flags) |
dev_t dev; |
struct vnode *devvp; |
struct uio *uio; |
struct uio *uio; |
int flags; |
int flags; |
{ |
{ |
int unit = ccdunit(dev); |
|
struct ccd_softc *cs; |
struct ccd_softc *cs; |
|
|
|
cs = vdev_privdata(devvp); |
#ifdef DEBUG |
#ifdef DEBUG |
if (ccddebug & CCDB_FOLLOW) |
if (ccddebug & CCDB_FOLLOW) |
printf("ccdwrite(0x%x, %p)\n", dev, uio); |
printf("ccdwrite(0x%x, %p)\n", vdev_rdev(devvp), uio); |
#endif |
#endif |
if (unit >= numccd) |
|
return (ENXIO); |
|
cs = &ccd_softc[unit]; |
|
|
|
if ((cs->sc_flags & CCDF_INITED) == 0) |
if ((cs->sc_flags & CCDF_INITED) == 0) |
return (ENXIO); |
return (ENXIO); |
|
|
Line 939 ccdwrite(dev, uio, flags) |
|
Line 947 ccdwrite(dev, uio, flags) |
|
* in particular, for raw I/O. Underlying devices might have some |
* in particular, for raw I/O. Underlying devices might have some |
* non-obvious limits, because of the copy to user-space. |
* non-obvious limits, because of the copy to user-space. |
*/ |
*/ |
return (physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio)); |
return (physio(ccdstrategy, NULL, devvp, B_WRITE, minphys, uio)); |
} |
} |
|
|
int |
int |
ccdioctl(dev, cmd, data, flag, p) |
ccdioctl(devvp, cmd, data, flag, p) |
dev_t dev; |
struct vnode *devvp; |
u_long cmd; |
u_long cmd; |
caddr_t data; |
caddr_t data; |
int flag; |
int flag; |
struct proc *p; |
struct proc *p; |
{ |
{ |
int unit = ccdunit(dev); |
|
int i, j, lookedup = 0, error; |
|
int part, pmask; |
|
struct ccd_softc *cs; |
struct ccd_softc *cs; |
struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; |
struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; |
|
int i, j, lookedup = 0, error; |
|
dev_t rdev; |
|
int part, pmask; |
char **cpp; |
char **cpp; |
struct vnode **vpp; |
struct vnode **vpp; |
#ifdef __HAVE_OLD_DISKLABEL |
#ifdef __HAVE_OLD_DISKLABEL |
struct disklabel newlabel; |
struct disklabel newlabel; |
#endif |
#endif |
|
|
if (unit >= numccd) |
rdev = vdev_rdev(devvp); |
return (ENXIO); |
cs = vdev_privdata(devvp); |
cs = &ccd_softc[unit]; |
|
|
|
/* Must be open for writes for these commands... */ |
/* Must be open for writes for these commands... */ |
switch (cmd) { |
switch (cmd) { |
Line 1090 ccdioctl(dev, cmd, data, flag, p) |
|
Line 1097 ccdioctl(dev, cmd, data, flag, p) |
|
* because space for the disklabel is allocated |
* because space for the disklabel is allocated |
* in disk_attach(); |
* in disk_attach(); |
*/ |
*/ |
ccio->ccio_unit = unit; |
ccio->ccio_unit = DISKUNIT(rdev); |
ccio->ccio_size = cs->sc_size; |
ccio->ccio_size = cs->sc_size; |
|
|
/* Attach the disk. */ |
/* Attach the disk. */ |
disk_attach(&cs->sc_dkdev); |
disk_attach(&cs->sc_dkdev); |
|
|
/* Try and read the disklabel. */ |
/* Try and read the disklabel. */ |
ccdgetdisklabel(dev); |
ccdgetdisklabel(devvp); |
break; |
break; |
|
|
case CCDIOCCLR: |
case CCDIOCCLR: |
Line 1106 ccdioctl(dev, cmd, data, flag, p) |
|
Line 1113 ccdioctl(dev, cmd, data, flag, p) |
|
* or if both the character and block flavors of this |
* or if both the character and block flavors of this |
* partition are open. |
* partition are open. |
*/ |
*/ |
part = DISKPART(dev); |
part = DISKPART(rdev); |
pmask = (1 << part); |
pmask = (1 << part); |
if ((cs->sc_dkdev.dk_openmask & ~pmask) || |
if ((cs->sc_dkdev.dk_openmask & ~pmask) || |
((cs->sc_dkdev.dk_bopenmask & pmask) && |
((cs->sc_dkdev.dk_bopenmask & pmask) && |
Line 1164 ccdioctl(dev, cmd, data, flag, p) |
|
Line 1171 ccdioctl(dev, cmd, data, flag, p) |
|
case DIOCGPART: |
case DIOCGPART: |
((struct partinfo *)data)->disklab = cs->sc_dkdev.dk_label; |
((struct partinfo *)data)->disklab = cs->sc_dkdev.dk_label; |
((struct partinfo *)data)->part = |
((struct partinfo *)data)->part = |
&cs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; |
&cs->sc_dkdev.dk_label->d_partitions[DISKPART(rdev)]; |
break; |
break; |
|
|
case DIOCWDINFO: |
case DIOCWDINFO: |
Line 1194 ccdioctl(dev, cmd, data, flag, p) |
|
Line 1201 ccdioctl(dev, cmd, data, flag, p) |
|
|| cmd == ODIOCWDINFO |
|| cmd == ODIOCWDINFO |
#endif |
#endif |
) |
) |
error = writedisklabel(CCDLABELDEV(dev), |
error = writedisklabel(devvp, ccdstrategy, |
ccdstrategy, cs->sc_dkdev.dk_label, |
cs->sc_dkdev.dk_label, |
cs->sc_dkdev.dk_cpulabel); |
cs->sc_dkdev.dk_cpulabel); |
} |
} |
|
|
|
|
ccdsize(dev) |
ccdsize(dev) |
dev_t dev; |
dev_t dev; |
{ |
{ |
|
#if 1 /* XXXthorpej */ |
|
return (-1); |
|
#else |
struct ccd_softc *cs; |
struct ccd_softc *cs; |
struct disklabel *lp; |
struct disklabel *lp; |
int part, unit, omask, size; |
int part, unit, omask, size; |
|
|
return (-1); |
return (-1); |
|
|
return (size); |
return (size); |
|
#endif |
} |
} |
|
|
int |
int |
Line 1376 ccdgetdefaultlabel(cs, lp) |
|
Line 1387 ccdgetdefaultlabel(cs, lp) |
|
* up. |
* up. |
*/ |
*/ |
static void |
static void |
ccdgetdisklabel(dev) |
ccdgetdisklabel(devvp) |
dev_t dev; |
struct vnode *devvp; |
{ |
{ |
int unit = ccdunit(dev); |
struct ccd_softc *cs; |
struct ccd_softc *cs = &ccd_softc[unit]; |
|
char *errstring; |
char *errstring; |
struct disklabel *lp = cs->sc_dkdev.dk_label; |
struct disklabel *lp; |
struct cpu_disklabel *clp = cs->sc_dkdev.dk_cpulabel; |
struct cpu_disklabel *clp; |
|
|
memset(clp, 0, sizeof(*clp)); |
memset(clp, 0, sizeof(*clp)); |
|
|
|
cs = vdev_privdata(devvp); |
|
lp = cs->sc_dkdev.dk_label; |
|
clp = cs->sc_dkdev.dk_cpulabel; |
|
|
ccdgetdefaultlabel(cs, lp); |
ccdgetdefaultlabel(cs, lp); |
|
|
/* |
/* |
* Call the generic disklabel extraction routine. |
* Call the generic disklabel extraction routine. |
*/ |
*/ |
errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy, |
errstring = readdisklabel(devvp, ccdstrategy, |
cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel); |
cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel); |
if (errstring) |
if (errstring) |
ccdmakedisklabel(cs); |
ccdmakedisklabel(cs); |