/* $NetBSD: dpti.c,v 1.51 2023/09/07 20:07:03 ad Exp $ */
/*-
* Copyright (c) 2001, 2007, 2023 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Doran.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1996-2000 Distributed Processing Technology Corporation
* Copyright (c) 2000 Adaptec Corporation
* All rights reserved.
*
* TERMS AND CONDITIONS OF USE
*
* Redistribution and use in source form, with or without modification, are
* permitted provided that redistributions of source code must retain the
* above copyright notice, this list of conditions and the following disclaimer.
*
* This software is provided `as is' by Adaptec and any express or implied
* warranties, including, but not limited to, the implied warranties of
* merchantability and fitness for a particular purpose, are disclaimed. In no
* event shall Adaptec be liable for any direct, indirect, incidental, special,
* exemplary or consequential damages (including, but not limited to,
* procurement of substitute goods or services; loss of use, data, or profits;
* or business interruptions) however caused and on any theory of liability,
* whether in contract, strict liability, or tort (including negligence or
* otherwise) arising in any way out of the use of this driver software, even
* if advised of the possibility of such damage.
*/
/*
* Tell the world what we are. The description in the signature
* must be no more than 46 bytes long (see dptivar.h).
*/
printf(": DPT/Adaptec RAID management interface\n");
snprintf(dpti_sig.dsDescription, sizeof(dpti_sig.dsDescription),
"NetBSD %s I2O OSM", osrelease);
/*
* Copy in the message frame header and determine the size of the
* full message frame.
*/
if ((rv = copyin(data, &mh, sizeof(mh))) != 0) {
DPRINTF(("%s: message copyin failed\n",
device_xname(sc->sc_dev)));
return (rv);
}
/*
* Handle special commands.
*/
switch (mh.msgfunc >> 24) {
case I2O_EXEC_IOP_RESET:
printf("%s: I2O_EXEC_IOP_RESET not implemented\n",
device_xname(sc->sc_dev));
return (EOPNOTSUPP);
case I2O_EXEC_OUTBOUND_INIT:
printf("%s: I2O_EXEC_OUTBOUND_INIT not implemented\n",
device_xname(sc->sc_dev));
return (EOPNOTSUPP);
case I2O_EXEC_SYS_TAB_SET:
printf("%s: I2O_EXEC_SYS_TAB_SET not implemented\n",
device_xname(sc->sc_dev));
return (EOPNOTSUPP);
case I2O_EXEC_STATUS_GET:
if ((rv = iop_status_get(iop, 0)) == 0)
rv = copyout(&iop->sc_status, (char *)data + msgsize,
sizeof(iop->sc_status));
return (rv);
}
/*
* Copy in the full message frame.
*/
if ((rv = copyin(data, mbtmp, msgsize)) != 0) {
DPRINTF(("%s: full message copyin failed\n",
device_xname(sc->sc_dev)));
return (rv);
}
/*
* Determine the size of the reply frame, and copy it in.
*/
if ((rv = copyin((char *)data + msgsize, &rh, sizeof(rh))) != 0) {
DPRINTF(("%s: reply copyin failed\n",
device_xname(sc->sc_dev)));
return (rv);
}
if ((rv = copyin((char *)data + msgsize, rbtmp, repsize)) != 0) {
DPRINTF(("%s: reply too large\n", device_xname(sc->sc_dev)));
return (rv);
}
/*
* If the message has a scatter gather list, it must be comprised of
* simple elements. If any one transfer contains multiple segments,
* we allocate a temporary buffer for it; otherwise, the buffer will
* be mapped directly.
*/
mapped = 0;
if ((sgoff = ((mh.msgflags >> 4) & 15)) != 0) {
if ((sgoff + 2) > (msgsize >> 2)) {
DPRINTF(("%s: invalid message size fields\n",
device_xname(sc->sc_dev)));
return (EINVAL);
}
/*
* The buffer has multiple segments. Determine the
* total size.
*/
nfrag = 0;
sz = 0;
for (; p <= pmax; p += 2) {
if (nfrag == DPTI_MAX_SEGS) {
DPRINTF(("%s: too many segments\n",
device_xname(sc->sc_dev)));
goto bad;
}