Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Mar 2010 12:01:35 +0000 (UTC)
From:      Attilio Rao <attilio@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r205877 - stable/7/sys/dev/aac
Message-ID:  <201003301201.o2UC1ZbX072520@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: attilio
Date: Tue Mar 30 12:01:35 2010
New Revision: 205877
URL: http://svn.freebsd.org/changeset/base/205877

Log:
  MFC r205160:
  Checkin a facility for specifying a passthrough FIB from userland.
  arcconf tool by Adaptec already seems to use for identifying the
  Serial Number of the devices.
  
  Sponsored by:	Sandvine Incorporated

Modified:
  stable/7/sys/dev/aac/aac.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/dev/aac/aac.c
==============================================================================
--- stable/7/sys/dev/aac/aac.c	Tue Mar 30 11:46:43 2010	(r205876)
+++ stable/7/sys/dev/aac/aac.c	Tue Mar 30 12:01:35 2010	(r205877)
@@ -3067,7 +3067,147 @@ out:
 static int
 aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg)
 {
-	return (EINVAL);
+	struct aac_command *cm;
+	struct aac_event *event;
+	struct aac_fib *fib;
+	struct aac_srb *srbcmd, *user_srb;
+	struct aac_sg_entry *sge;
+	struct aac_sg_entry64 *sge64;
+	void *srb_sg_address, *ureply;
+	uint32_t fibsize, srb_sg_bytecount;
+	int error, transfer_data;
+
+	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+	cm = NULL;
+	transfer_data = 0;
+	fibsize = 0;
+	user_srb = (struct aac_srb *)arg;
+
+	mtx_lock(&sc->aac_io_lock);
+	if (aac_alloc_command(sc, &cm)) {
+		 event = malloc(sizeof(struct aac_event), M_AACBUF,
+		    M_NOWAIT | M_ZERO);
+		if (event == NULL) {
+			error = EBUSY;
+			mtx_unlock(&sc->aac_io_lock);
+			goto out;
+		}
+		event->ev_type = AAC_EVENT_CMFREE;
+		event->ev_callback = aac_ioctl_event;
+		event->ev_arg = &cm;
+		aac_add_event(sc, event);
+		msleep(cm, &sc->aac_io_lock, 0, "aacraw", 0);
+	}
+	mtx_unlock(&sc->aac_io_lock);
+
+	cm->cm_data = NULL;
+	fib = cm->cm_fib;
+	srbcmd = (struct aac_srb *)fib->data;
+	error = copyin(&user_srb->data_len, &fibsize, sizeof(uint32_t));
+	if (error != 0)
+		goto out;
+	if (fibsize > (sc->aac_max_fib_size - sizeof(struct aac_fib_header))) {
+		error = EINVAL;
+		goto out;
+	}
+	error = copyin(user_srb, srbcmd, fibsize);
+	if (error != 0)
+		goto out;
+	srbcmd->function = 0;
+	srbcmd->retry_limit = 0;
+	if (srbcmd->sg_map.SgCount > 1) {
+		error = EINVAL;
+		goto out;
+	}
+
+	/* Retrieve correct SG entries. */
+	if (fibsize == (sizeof(struct aac_srb) +
+	    srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry))) {
+		sge = srbcmd->sg_map.SgEntry;
+		sge64 = NULL;
+		srb_sg_bytecount = sge->SgByteCount;
+#ifdef __amd64__
+		srb_sg_address = (void *)(uint64_t)sge->SgAddress;
+#else
+		srb_sg_address = (void *)sge->SgAddress;
+#endif
+	}
+#ifdef __amd64__
+	else if (fibsize == (sizeof(struct aac_srb) +
+	    srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry64))) {
+		sge = NULL;
+		sge64 = (struct aac_sg_entry64 *)srbcmd->sg_map.SgEntry;
+		srb_sg_bytecount = sge64->SgByteCount;
+		srb_sg_address = (void *)sge64->SgAddress;
+		if (sge64->SgAddress > 0xffffffffull &&
+		    (sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
+			error = EINVAL;
+			goto out;
+		}
+	}
+#endif
+	else {
+		error = EINVAL;
+		goto out;
+	}
+	ureply = (char *)arg + fibsize;
+	srbcmd->data_len = srb_sg_bytecount;
+	if (srbcmd->sg_map.SgCount == 1)
+		transfer_data = 1;
+
+	cm->cm_sgtable = (struct aac_sg_table *)&srbcmd->sg_map;
+	if (transfer_data) {
+		cm->cm_datalen = srb_sg_bytecount;
+		cm->cm_data = malloc(cm->cm_datalen, M_AACBUF, M_NOWAIT);
+		if (cm->cm_data == NULL) {
+			error = ENOMEM;
+			goto out;
+		}
+		if (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN)
+			cm->cm_flags |= AAC_CMD_DATAIN;
+		if (srbcmd->flags & AAC_SRB_FLAGS_DATA_OUT) {
+			cm->cm_flags |= AAC_CMD_DATAOUT;
+			error = copyin(srb_sg_address, cm->cm_data,
+			    cm->cm_datalen);
+			if (error != 0)
+				goto out;
+		}
+	}
+
+	fib->Header.Size = sizeof(struct aac_fib_header) +
+	    sizeof(struct aac_srb);
+	fib->Header.XferState =
+	    AAC_FIBSTATE_HOSTOWNED   |
+	    AAC_FIBSTATE_INITIALISED |
+	    AAC_FIBSTATE_EMPTY       |
+	    AAC_FIBSTATE_FROMHOST    |
+	    AAC_FIBSTATE_REXPECTED   |
+	    AAC_FIBSTATE_NORM        |
+	    AAC_FIBSTATE_ASYNC       |
+	    AAC_FIBSTATE_FAST_RESPONSE;
+	fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) != 0 ?
+	    ScsiPortCommandU64 : ScsiPortCommand;
+
+	mtx_lock(&sc->aac_io_lock);
+	aac_wait_command(cm);
+	mtx_unlock(&sc->aac_io_lock);
+
+	if (transfer_data && (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN) != 0) {
+		error = copyout(cm->cm_data, srb_sg_address, cm->cm_datalen);
+		if (error != 0)
+			goto out;
+	}
+	error = copyout(fib->data, ureply, sizeof(struct aac_srb_response));
+out:
+	if (cm != NULL) {
+		if (cm->cm_data != NULL)
+			free(cm->cm_data, M_AACBUF);
+		mtx_lock(&sc->aac_io_lock);
+		aac_release_command(cm);
+		mtx_unlock(&sc->aac_io_lock);
+	}
+	return(error);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003301201.o2UC1ZbX072520>