if (err = copyin(xio->dptr, dvmabuf, xio->dlen)) {
if ((err = copyin(xio->dptr, dvmabuf, xio->dlen))) {
xdc_ioctlcmd(xd, dev, xio)	struct xd_softc *xd;	dev_t   dev;	struct xd_iocmd *xio;{	int     s, err, rqno, dummy;	caddr_t dvmabuf = NULL;	struct xdc_softc *xdcsc;	/* check sanity of requested command */	switch (xio->cmd) {	case XDCMD_NOP:	/* no op: everything should be zero */		if (xio->subfn || xio->dptr || xio->dlen ||		    xio->block || xio->sectcnt)			return (EINVAL);		break;	case XDCMD_RD:		/* read / write sectors (up to XD_IOCMD_MAXS) */	case XDCMD_WR:		if (xio->subfn || xio->sectcnt > XD_IOCMD_MAXS ||		    xio->sectcnt * XDFM_BPS != xio->dlen || xio->dptr == NULL)			return (EINVAL);		break;	case XDCMD_SK:		/* seek: doesn't seem useful to export this */		return (EINVAL);	case XDCMD_WRP:	/* write parameters */		return (EINVAL);/* not useful, except maybe drive				 * parameters... but drive parameters should				 * go via disklabel changes */	case XDCMD_RDP:	/* read parameters */		if (xio->subfn != XDFUN_DRV ||		    xio->dlen || xio->block || xio->dptr)			return (EINVAL);	/* allow read drive params to						 * get hw_spt */		xio->sectcnt = xd->hw_spt;	/* we already know the answer */		return (0);		break;	case XDCMD_XRD:	/* extended read/write */	case XDCMD_XWR:		switch (xio->subfn) {		case XDFUN_THD:/* track headers */			if (xio->sectcnt != xd->hw_spt ||			    (xio->block % xd->nsect) != 0 ||			    xio->dlen != XD_IOCMD_HSZ * xd->hw_spt ||			    xio->dptr == NULL)				return (EINVAL);			xio->sectcnt = 0;			break;		case XDFUN_FMT:/* NOTE: also XDFUN_VFY */			if (xio->cmd == XDCMD_XRD)				return (EINVAL);	/* no XDFUN_VFY */			if (xio->sectcnt || xio->dlen ||			    (xio->block % xd->nsect) != 0 || xio->dptr)				return (EINVAL);			break;		case XDFUN_HDR:/* header, header verify, data, data ECC */			return (EINVAL);	/* not yet */		case XDFUN_DM:	/* defect map */		case XDFUN_DMX:/* defect map (alternate location) */			if (xio->sectcnt || xio->dlen != XD_IOCMD_DMSZ ||			    (xio->block % xd->nsect) != 0 || xio->dptr == NULL)				return (EINVAL);			break;		default:			return (EINVAL);		}		break;	case XDCMD_TST:	/* diagnostics */		return (EINVAL);	default:		return (EINVAL);/* ??? */	}	/* create DVMA buffer for request if needed */	if (xio->dlen) {		dvmabuf = dvma_malloc(xio->dlen);		if (xio->cmd == XDCMD_WR || xio->cmd == XDCMD_XWR) {			if (err = copyin(xio->dptr, dvmabuf, xio->dlen)) {				dvma_free(dvmabuf, xio->dlen);				return (err);			}		}	}	/* do it! */	err = 0;	xdcsc = xd->parent;	s = splbio();	rqno = xdc_cmd(xdcsc, xio->cmd, xio->subfn, xd->xd_drive, xio->block,	    xio->sectcnt, dvmabuf, XD_SUB_WAIT);	if (rqno == XD_ERR_FAIL) {		err = EIO;		goto done;	}	xio->errno = xdcsc->reqs[rqno].errno;	xio->tries = xdcsc->reqs[rqno].tries;	XDC_DONE(xdcsc, rqno, dummy);	if (xio->cmd == XDCMD_RD || xio->cmd == XDCMD_XRD)		err = copyout(dvmabuf, xio->dptr, xio->dlen);done:	splx(s);	if (dvmabuf)		dvma_free(dvmabuf, xio->dlen);	return (err);}