svn commit: r205160 - head/sys/dev/aac

Attilio Rao attilio at freebsd.org
Sun Mar 14 22:40:07 UTC 2010


We can close this ticket now.
There is something else we should do related to the aac driver itself?
Maybe handling the problem reported in the last filled PR?

Attilio


---------- Forwarded message ----------
From: Attilio Rao <attilio at freebsd.org>
Date: 2010/3/14
Subject: svn commit: r205160 - head/sys/dev/aac
To: src-committers at freebsd.org, svn-src-all at freebsd.org,
svn-src-head at freebsd.org


Author: attilio
Date: Sun Mar 14 22:38:18 2010
New Revision: 205160
URL: http://svn.freebsd.org/changeset/base/205160

Log:
 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.
 Some simple things (like FIB setup and bound checks) are retrieved
 from the Adaptec's driver, but this implementation is quite different
 because it does use the normal buffer dmat area for loading segments
 and not a special one (like the Adaptec's one does).

 Sponsored by: Sandvine Incorporated
 Discussed with:       emaste, scottl
 Reviewed by:  emaste, scottl
 MFC:          2 weeks

Modified:
 head/sys/dev/aac/aac.c

Modified: head/sys/dev/aac/aac.c
==============================================================================
--- head/sys/dev/aac/aac.c      Sun Mar 14 21:14:25 2010        (r205159)
+++ head/sys/dev/aac/aac.c      Sun Mar 14 22:38:18 2010        (r205160)
@@ -3063,7 +3063,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);
 }

 /*



-- 
Peace can only be achieved by understanding - A. Einstein


More information about the svn-src-all mailing list