svn commit: r205876 - stable/8/sys/dev/aac
Attilio Rao
attilio at FreeBSD.org
Tue Mar 30 11:46:44 UTC 2010
Author: attilio
Date: Tue Mar 30 11:46:43 2010
New Revision: 205876
URL: http://svn.freebsd.org/changeset/base/205876
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/8/sys/dev/aac/aac.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
Modified: stable/8/sys/dev/aac/aac.c
==============================================================================
--- stable/8/sys/dev/aac/aac.c Tue Mar 30 11:19:29 2010 (r205875)
+++ stable/8/sys/dev/aac/aac.c Tue Mar 30 11:46:43 2010 (r205876)
@@ -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);
}
/*
More information about the svn-src-all
mailing list