version 1.75, 2014/11/22 11:59:33 |
version 1.75.2.3, 2015/12/27 12:09:49 |
Line 102 static int dkwedge_cleanup_parent(struct |
|
Line 102 static int dkwedge_cleanup_parent(struct |
|
static int dkwedge_detach(device_t, int); |
static int dkwedge_detach(device_t, int); |
static void dkwedge_delall1(struct disk *, bool); |
static void dkwedge_delall1(struct disk *, bool); |
static int dkwedge_del1(struct dkwedge_info *, int); |
static int dkwedge_del1(struct dkwedge_info *, int); |
|
static struct vnode *dk_open_parent(dev_t, int); |
|
static int dk_close_parent(struct vnode *, int); |
|
|
static dev_type_open(dkopen); |
static dev_type_open(dkopen); |
static dev_type_close(dkclose); |
static dev_type_close(dkclose); |
Line 258 dkwedge_array_expand(void) |
|
Line 260 dkwedge_array_expand(void) |
|
} |
} |
|
|
static void |
static void |
dkgetproperties(struct disk *disk, struct dkwedge_info *dkw) |
dk_set_geometry(struct dkwedge_softc *sc, struct disk *pdk) |
{ |
{ |
struct disk_geom *dg = &disk->dk_geom; |
struct disk *dk = &sc->sc_dk; |
|
struct disk_geom *dg = &dk->dk_geom; |
|
|
memset(dg, 0, sizeof(*dg)); |
memset(dg, 0, sizeof(*dg)); |
|
|
dg->dg_secperunit = dkw->dkw_size >> disk->dk_blkshift; |
dg->dg_secperunit = sc->sc_size; |
dg->dg_secsize = DEV_BSIZE << disk->dk_blkshift; |
dg->dg_secsize = DEV_BSIZE << pdk->dk_blkshift; |
|
|
|
/* fake numbers, 1 cylinder is 1 MB with default sector size */ |
dg->dg_nsectors = 32; |
dg->dg_nsectors = 32; |
dg->dg_ntracks = 64; |
dg->dg_ntracks = 64; |
/* XXX: why is that dkw->dkw_size instead of secperunit?!?! */ |
dg->dg_ncylinders = dg->dg_secperunit / (dg->dg_nsectors * dg->dg_ntracks); |
dg->dg_ncylinders = dkw->dkw_size / (dg->dg_nsectors * dg->dg_ntracks); |
|
|
|
disk_set_info(NULL, disk, "ESDI"); |
disk_set_info(sc->sc_dev, dk, NULL); |
} |
} |
|
|
/* |
/* |
Line 453 dkwedge_add(struct dkwedge_info *dkw) |
|
Line 457 dkwedge_add(struct dkwedge_info *dkw) |
|
*/ |
*/ |
|
|
disk_init(&sc->sc_dk, device_xname(sc->sc_dev), NULL); |
disk_init(&sc->sc_dk, device_xname(sc->sc_dev), NULL); |
disk_blocksize(&sc->sc_dk, DEV_BSIZE << pdk->dk_blkshift); |
dk_set_geometry(sc, pdk); |
dkgetproperties(&sc->sc_dk, dkw); |
|
disk_attach(&sc->sc_dk); |
disk_attach(&sc->sc_dk); |
|
|
/* Disk wedge is ready for use! */ |
/* Disk wedge is ready for use! */ |
sc->sc_state = DKW_STATE_RUNNING; |
sc->sc_state = DKW_STATE_RUNNING; |
|
|
/* Announce our arrival. */ |
/* Announce our arrival. */ |
aprint_normal("%s at %s: %s\n", device_xname(sc->sc_dev), pdk->dk_name, |
aprint_normal( |
sc->sc_wname); /* XXX Unicode */ |
"%s at %s: \"%s\", %"PRIu64" blocks at %"PRId64", type: %s\n", |
aprint_normal("%s: %"PRIu64" blocks at %"PRId64", type: %s\n", |
device_xname(sc->sc_dev), pdk->dk_name, |
device_xname(sc->sc_dev), sc->sc_size, sc->sc_offset, sc->sc_ptype); |
sc->sc_wname, /* XXX Unicode */ |
|
sc->sc_size, sc->sc_offset, |
|
sc->sc_ptype[0] == '\0' ? "<unknown>" : sc->sc_ptype); |
|
|
return (0); |
return (0); |
} |
} |
Line 679 dkwedge_delall1(struct disk *pdk, bool i |
|
Line 684 dkwedge_delall1(struct disk *pdk, bool i |
|
* dkwedge_list: [exported function] |
* dkwedge_list: [exported function] |
* |
* |
* List all of the wedges on a particular disk. |
* List all of the wedges on a particular disk. |
* If p == NULL, the buffer is in kernel space. Otherwise, it is |
|
* in user space of the specified process. |
|
*/ |
*/ |
int |
int |
dkwedge_list(struct disk *pdk, struct dkwedge_list *dkwl, struct lwp *l) |
dkwedge_list(struct disk *pdk, struct dkwedge_list *dkwl, struct lwp *l) |
Line 944 dkwedge_read(struct disk *pdk, struct vn |
|
Line 947 dkwedge_read(struct disk *pdk, struct vn |
|
{ |
{ |
buf_t *bp; |
buf_t *bp; |
int error; |
int error; |
|
bool isopen; |
|
dev_t bdev; |
|
struct vnode *bdvp; |
|
|
/* |
/* |
* The kernel cannot read from a character device vnode |
* The kernel cannot read from a character device vnode |
* as physio() only handles user memory. |
* as physio() only handles user memory. |
* |
* |
* Determine the corresponding block device and call into |
* If the block device has already been opened by a wedge |
* the driver directly. |
* use that vnode and temporarily bump the open counter. |
|
* |
|
* Otherwise try to open the block device. |
*/ |
*/ |
|
|
bp = getiobuf(vp, true); |
bdev = devsw_chr2blk(vp->v_rdev); |
|
|
|
mutex_enter(&pdk->dk_rawlock); |
|
if (pdk->dk_rawopens != 0) { |
|
KASSERT(pdk->dk_rawvp != NULL); |
|
isopen = true; |
|
++pdk->dk_rawopens; |
|
bdvp = pdk->dk_rawvp; |
|
} else { |
|
isopen = false; |
|
bdvp = dk_open_parent(bdev, FREAD); |
|
} |
|
mutex_exit(&pdk->dk_rawlock); |
|
|
|
if (bdvp == NULL) |
|
return EBUSY; |
|
|
|
bp = getiobuf(bdvp, true); |
bp->b_flags = B_READ; |
bp->b_flags = B_READ; |
bp->b_cflags = BC_BUSY; |
bp->b_cflags = BC_BUSY; |
bp->b_dev = devsw_chr2blk(vp->v_rdev); |
bp->b_dev = bdev; |
bp->b_data = tbuf; |
bp->b_data = tbuf; |
bp->b_bufsize = bp->b_bcount = len; |
bp->b_bufsize = bp->b_bcount = len; |
bp->b_blkno = blkno; |
bp->b_blkno = blkno; |
bp->b_cylinder = 0; |
bp->b_cylinder = 0; |
bp->b_error = 0; |
bp->b_error = 0; |
|
|
error = bdev_open(bp->b_dev, FREAD, S_IFBLK, curlwp); |
VOP_STRATEGY(bdvp, bp); |
if (error) |
|
return error; |
|
|
|
bdev_strategy(bp); |
|
error = biowait(bp); |
error = biowait(bp); |
putiobuf(bp); |
putiobuf(bp); |
|
|
bdev_close(bp->b_dev, FREAD, S_IFBLK, curlwp); |
mutex_enter(&pdk->dk_rawlock); |
|
if (isopen) { |
|
--pdk->dk_rawopens; |
|
} else { |
|
dk_close_parent(bdvp, FREAD); |
|
} |
|
mutex_exit(&pdk->dk_rawlock); |
|
|
return error; |
return error; |
} |
} |
Line 994 dkwedge_lookup(dev_t dev) |
|
Line 1021 dkwedge_lookup(dev_t dev) |
|
return (dkwedges[unit]); |
return (dkwedges[unit]); |
} |
} |
|
|
|
static struct vnode * |
|
dk_open_parent(dev_t dev, int mode) |
|
{ |
|
struct vnode *vp; |
|
int error; |
|
|
|
error = bdevvp(dev, &vp); |
|
if (error) |
|
return NULL; |
|
|
|
error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
|
if (error) { |
|
vrele(vp); |
|
return NULL; |
|
} |
|
error = VOP_OPEN(vp, mode, NOCRED); |
|
if (error) { |
|
vput(vp); |
|
return NULL; |
|
} |
|
|
|
/* VOP_OPEN() doesn't do this for us. */ |
|
if (mode & FWRITE) { |
|
mutex_enter(vp->v_interlock); |
|
vp->v_writecount++; |
|
mutex_exit(vp->v_interlock); |
|
} |
|
|
|
VOP_UNLOCK(vp); |
|
|
|
return vp; |
|
} |
|
|
|
static int |
|
dk_close_parent(struct vnode *vp, int mode) |
|
{ |
|
int error; |
|
|
|
error = vn_close(vp, mode, NOCRED); |
|
return error; |
|
} |
|
|
/* |
/* |
* dkopen: [devsw entry point] |
* dkopen: [devsw entry point] |
* |
* |
Line 1022 dkopen(dev_t dev, int flags, int fmt, st |
|
Line 1091 dkopen(dev_t dev, int flags, int fmt, st |
|
if (sc->sc_dk.dk_openmask == 0) { |
if (sc->sc_dk.dk_openmask == 0) { |
if (sc->sc_parent->dk_rawopens == 0) { |
if (sc->sc_parent->dk_rawopens == 0) { |
KASSERT(sc->sc_parent->dk_rawvp == NULL); |
KASSERT(sc->sc_parent->dk_rawvp == NULL); |
error = bdevvp(sc->sc_pdev, &vp); |
vp = dk_open_parent(sc->sc_pdev, FREAD | FWRITE); |
if (error) |
if (vp == NULL) |
goto popen_fail; |
|
error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
|
if (error) { |
|
vrele(vp); |
|
goto popen_fail; |
goto popen_fail; |
} |
|
error = VOP_OPEN(vp, FREAD | FWRITE, NOCRED); |
|
if (error) { |
|
vput(vp); |
|
goto popen_fail; |
|
} |
|
/* VOP_OPEN() doesn't do this for us. */ |
|
mutex_enter(vp->v_interlock); |
|
vp->v_writecount++; |
|
mutex_exit(vp->v_interlock); |
|
VOP_UNLOCK(vp); |
|
sc->sc_parent->dk_rawvp = vp; |
sc->sc_parent->dk_rawvp = vp; |
} |
} |
sc->sc_parent->dk_rawopens++; |
sc->sc_parent->dk_rawopens++; |
Line 1075 dklastclose(struct dkwedge_softc *sc) |
|
Line 1129 dklastclose(struct dkwedge_softc *sc) |
|
|
|
if (doclose) { |
if (doclose) { |
KASSERT(sc->sc_parent->dk_rawvp != NULL); |
KASSERT(sc->sc_parent->dk_rawvp != NULL); |
error = vn_close(sc->sc_parent->dk_rawvp, |
dk_close_parent(sc->sc_parent->dk_rawvp, FREAD | FWRITE); |
FREAD | FWRITE, NOCRED); |
|
sc->sc_parent->dk_rawvp = NULL; |
sc->sc_parent->dk_rawvp = NULL; |
} |
} |
|
|
Line 1113 dkclose(dev_t dev, int flags, int fmt, s |
|
Line 1166 dkclose(dev_t dev, int flags, int fmt, s |
|
|
|
if (sc->sc_dk.dk_openmask == 0) |
if (sc->sc_dk.dk_openmask == 0) |
error = dklastclose(sc); /* releases dk_rawlock */ |
error = dklastclose(sc); /* releases dk_rawlock */ |
else |
else |
mutex_exit(&sc->sc_parent->dk_rawlock); |
mutex_exit(&sc->sc_parent->dk_rawlock); |
|
|
mutex_exit(&sc->sc_dk.dk_openlock); |
mutex_exit(&sc->sc_dk.dk_openlock); |
Line 1357 dkioctl(dev_t dev, u_long cmd, void *dat |
|
Line 1410 dkioctl(dev_t dev, u_long cmd, void *dat |
|
if (sc->sc_parent->dk_rawvp == NULL) |
if (sc->sc_parent->dk_rawvp == NULL) |
return (ENXIO); |
return (ENXIO); |
|
|
error = disk_ioctl(&sc->sc_dk, cmd, data, flag, l); |
/* |
|
* We pass NODEV instead of our device to indicate we don't |
|
* want to handle disklabel ioctls |
|
*/ |
|
error = disk_ioctl(&sc->sc_dk, NODEV, cmd, data, flag, l); |
if (error != EPASSTHROUGH) |
if (error != EPASSTHROUGH) |
return (error); |
return (error); |
|
|
error = 0; |
error = 0; |
|
|
switch (cmd) { |
switch (cmd) { |
case DIOCCACHESYNC: |
case DIOCCACHESYNC: |
/* |
/* |