Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Add a pass-through ioctl for mfi(4), allowing userland to se...



details:   https://anonhg.NetBSD.org/src/rev/86f340cd08c1
branches:  trunk
changeset: 781642:86f340cd08c1
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Wed Sep 19 21:24:28 2012 +0000

description:
Add a pass-through ioctl for mfi(4), allowing userland to send raw commands
to the controller. This is compatible with the linux and FreeBSD
implementations.
Add the needed conversion for mfi ioctls in COMPAT_LINUX
Allocate a character major number, and create /dev/mfi0 by default
on amd64 and i386.
This allows (along with a hand-created /emul/linux/proc/devices file)
to run the MegaCLI linux binary provided by LSI.

diffstat:

 etc/MAKEDEV.tmpl                      |    8 +-
 etc/etc.amd64/MAKEDEV.conf            |    4 +-
 etc/etc.i386/MAKEDEV.conf             |    4 +-
 sys/compat/linux/common/linux_ioctl.c |   31 +++++-
 sys/conf/majors                       |    3 +-
 sys/dev/ic/mfi.c                      |  165 +++++++++++++++++++++++++++++++++-
 sys/dev/ic/mfiio.h                    |   93 +++++++++++++++++++
 sys/dev/ic/mfireg.h                   |    7 +-
 sys/dev/ic/mfivar.h                   |    5 +-
 9 files changed, 307 insertions(+), 13 deletions(-)

diffs (truncated from 484 to 300 lines):

diff -r b98e47627c7d -r 86f340cd08c1 etc/MAKEDEV.tmpl
--- a/etc/MAKEDEV.tmpl  Wed Sep 19 21:19:14 2012 +0000
+++ b/etc/MAKEDEV.tmpl  Wed Sep 19 21:24:28 2012 +0000
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#      $NetBSD: MAKEDEV.tmpl,v 1.158 2012/09/05 08:25:53 martin Exp $
+#      $NetBSD: MAKEDEV.tmpl,v 1.159 2012/09/19 21:24:28 bouyer Exp $
 #
 # Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -254,6 +254,7 @@
 #      lockstat kernel locking statistics
 #      magma*  Magma multiport serial/parallel cards
 #      midi*   MIDI
+#      mfi*    LSI MegaRAID/MegaSAS control interface
 #      mlx*    Mylex DAC960 control interface
 #      mly*    Mylex AcceleRAID/eXtremeRAID control interface
 #      np*     UNIBUS Ethernet co-processor interface, for downloading.
@@ -1557,6 +1558,11 @@
        mkdev iop$unit c %iop_chr% $unit
        ;;
 
+mfi[0-9]*)
+       unit=${i#mfi}
+       mkdev mfi$unit c %mfi_chr% $unit
+       ;;
+
 mlx[0-9]*)
        unit=${i#mlx}
        mkdev mlx$unit c %mlx_chr% $unit
diff -r b98e47627c7d -r 86f340cd08c1 etc/etc.amd64/MAKEDEV.conf
--- a/etc/etc.amd64/MAKEDEV.conf        Wed Sep 19 21:19:14 2012 +0000
+++ b/etc/etc.amd64/MAKEDEV.conf        Wed Sep 19 21:24:28 2012 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: MAKEDEV.conf,v 1.18 2012/04/07 17:22:10 christos Exp $
+# $NetBSD: MAKEDEV.conf,v 1.19 2012/09/19 21:24:29 bouyer Exp $
 
 # As of 2003-04-17, the "init" case must not create more than 890 entries.
 all_md)
@@ -11,7 +11,7 @@
        makedev bpf
        makedev ccd0 md0 ch0 random
        makedev cgd0 cgd1
-       makedev amr0 iop0 mlx0 mly0 dpti0 dpt0 twe0
+       makedev amr0 iop0 mfi0 mlx0 mly0 dpti0 dpt0 twe0
        makedev raid0 raid1 raid2 raid3
        makedev ld0 ld1 ld2 ld3
        makedev xbd0 xbd1 xbd2 xbd3 xen
diff -r b98e47627c7d -r 86f340cd08c1 etc/etc.i386/MAKEDEV.conf
--- a/etc/etc.i386/MAKEDEV.conf Wed Sep 19 21:19:14 2012 +0000
+++ b/etc/etc.i386/MAKEDEV.conf Wed Sep 19 21:24:28 2012 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: MAKEDEV.conf,v 1.23 2012/08/16 13:31:25 abs Exp $
+# $NetBSD: MAKEDEV.conf,v 1.24 2012/09/19 21:24:29 bouyer Exp $
 
 # As of 2005-03-15, the "init" case must not create more than 1024 entries.
 all_md)
@@ -11,7 +11,7 @@
        makedev bpf
        makedev ccd0 md0 ch0 random
        makedev cgd0 cgd1
-       makedev amr0 iop0 mlx0 mly0 dpti0 dpt0 twe0 icp0
+       makedev amr0 iop0 mfi0 mlx0 mly0 dpti0 dpt0 twe0 icp0
        makedev ed0 ed1
        makedev raid0 raid1 raid2 raid3
        makedev ld0 ld1 ld2 ld3
diff -r b98e47627c7d -r 86f340cd08c1 sys/compat/linux/common/linux_ioctl.c
--- a/sys/compat/linux/common/linux_ioctl.c     Wed Sep 19 21:19:14 2012 +0000
+++ b/sys/compat/linux/common/linux_ioctl.c     Wed Sep 19 21:24:28 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_ioctl.c,v 1.56 2011/10/14 09:23:28 hannken Exp $ */
+/*     $NetBSD: linux_ioctl.c,v 1.57 2012/09/19 21:24:29 bouyer Exp $  */
 
 /*-
  * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_ioctl.c,v 1.56 2011/10/14 09:23:28 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_ioctl.c,v 1.57 2012/09/19 21:24:29 bouyer Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "sequencer.h"
@@ -63,6 +63,10 @@
 #include <compat/ossaudio/ossaudio.h>
 #define LINUX_TO_OSS(v) ((const void *)(v))    /* do nothing, same ioctl() encoding */
 
+#include <dev/ic/mfiio.h>
+#define LINUX_MEGARAID_CMD     _LINUX_IOWR('M', 1, struct mfi_ioc_packet)
+#define LINUX_MEGARAID_GET_AEN _LINUX_IOW('M', 3, struct mfi_ioc_aen)
+
 /*
  * Most ioctl command are just converted to their NetBSD values,
  * and passed on. The ones that take structure pointers and (flag)
@@ -80,7 +84,28 @@
 
        switch (LINUX_IOCGROUP(SCARG(uap, com))) {
        case 'M':
-               error = oss_ioctl_mixer(l, LINUX_TO_OSS(uap), retval);
+               switch(SCARG(uap, com)) {
+               case LINUX_MEGARAID_CMD:
+               case LINUX_MEGARAID_GET_AEN:
+               {
+                       struct sys_ioctl_args ua;
+                       u_long com = 0;
+                       if (SCARG(uap, com) & IOC_IN)
+                               com |= IOC_OUT;
+                       if (SCARG(uap, com) & IOC_OUT)
+                               com |= IOC_IN;
+                       SCARG(&ua, fd) = SCARG(uap, fd);
+                       SCARG(&ua, com) = SCARG(uap, com);
+                       SCARG(&ua, com) &= ~IOC_DIRMASK;
+                       SCARG(&ua, com) |= com;
+                       SCARG(&ua, data) = SCARG(uap, data);
+                       error = sys_ioctl(l, (const void *)&ua, retval);
+                       break;
+               }
+               default:
+                       error = oss_ioctl_mixer(l, LINUX_TO_OSS(uap), retval);
+                       break;
+               }
                break;
        case 'Q':
                error = oss_ioctl_sequencer(l, LINUX_TO_OSS(uap), retval);
diff -r b98e47627c7d -r 86f340cd08c1 sys/conf/majors
--- a/sys/conf/majors   Wed Sep 19 21:19:14 2012 +0000
+++ b/sys/conf/majors   Wed Sep 19 21:24:28 2012 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.61 2012/01/22 06:44:30 christos Exp $
+# $NetBSD: majors,v 1.62 2012/09/19 21:24:29 bouyer Exp $
 #
 # Device majors for Machine-Independent drivers.
 #
@@ -50,3 +50,4 @@
 device-major filemon   char 202            filemon
 device-major iscsi     char 203            iscsi
 device-major tpm       char 204                   tpm
+device-major mfi       char 205                   mfi
diff -r b98e47627c7d -r 86f340cd08c1 sys/dev/ic/mfi.c
--- a/sys/dev/ic/mfi.c  Wed Sep 19 21:19:14 2012 +0000
+++ b/sys/dev/ic/mfi.c  Wed Sep 19 21:24:28 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mfi.c,v 1.46 2012/08/26 16:22:32 bouyer Exp $ */
+/* $NetBSD: mfi.c,v 1.47 2012/09/19 21:24:29 bouyer Exp $ */
 /* $OpenBSD: mfi.c,v 1.66 2006/11/28 23:59:45 dlg Exp $ */
 
 /*
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.46 2012/08/26 16:22:32 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.47 2012/09/19 21:24:29 bouyer Exp $");
 
 #include "bio.h"
 
@@ -86,6 +86,8 @@
 #include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/cpu.h>
+#include <sys/conf.h>
+#include <sys/kauth.h>
 
 #include <uvm/uvm_param.h>
 
@@ -100,6 +102,7 @@
 
 #include <dev/ic/mfireg.h>
 #include <dev/ic/mfivar.h>
+#include <dev/ic/mfiio.h>
 
 #if NBIO > 0
 #include <dev/biovar.h>
@@ -177,6 +180,16 @@
 static bool            mfi_suspend(device_t, const pmf_qual_t *);
 static bool            mfi_resume(device_t, const pmf_qual_t *);
 
+static dev_type_open(mfifopen);
+static dev_type_close(mfifclose);
+static dev_type_ioctl(mfifioctl);
+const struct cdevsw mfi_cdevsw = {
+       mfifopen, mfifclose, noread, nowrite, mfifioctl,
+       nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
+};
+
+extern struct cfdriver mfi_cd;
+
 static uint32_t        mfi_xscale_fw_state(struct mfi_softc *sc);
 static void            mfi_xscale_intr_ena(struct mfi_softc *sc);
 static void            mfi_xscale_intr_dis(struct mfi_softc *sc);
@@ -3472,3 +3485,151 @@
                workqueue_enqueue(sc->sc_ldsync_wq, &sc->sc_ldsync_wk, NULL);
        }
 }
+
+static int
+mfifopen(dev_t dev, int flag, int mode, struct lwp *l)
+{
+       struct mfi_softc *sc;
+
+       if ((sc = device_lookup_private(&mfi_cd, minor(dev))) == NULL)
+               return (ENXIO);
+       return (0);
+}
+
+static int
+mfifclose(dev_t dev, int flag, int mode, struct lwp *l)
+{
+       struct mfi_softc *sc;
+
+       sc = device_lookup_private(&mfi_cd, minor(dev));
+       return (0);
+}
+
+static int
+mfifioctl(dev_t dev, u_long cmd, void *data, int flag,
+    struct lwp *l)
+{
+       struct mfi_softc *sc;
+       struct mfi_ioc_packet *ioc = data;
+       uint8_t *udata;
+       struct mfi_ccb *ccb = NULL;
+       int ctx, i, s, error;
+       union mfi_sense_ptr sense_ptr;
+
+       switch(cmd) {
+       case MFI_CMD:
+               sc = device_lookup_private(&mfi_cd, ioc->mfi_adapter_no);
+               break;
+       default:
+               return ENOTTY;
+       }
+       if (sc == NULL)
+               return (ENXIO);
+       if (sc->sc_opened)
+               return (EBUSY);
+
+       switch(cmd) {
+       case MFI_CMD:
+               error = kauth_authorize_device_passthru(l->l_cred, dev,
+                   KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data);
+               if (error)
+                       return error;
+               if (ioc->mfi_sge_count > MAX_IOCTL_SGE)
+                       return EINVAL;
+               s = splbio();
+               if ((ccb = mfi_get_ccb(sc)) == NULL)
+                       return ENOMEM;
+               ccb->ccb_data = NULL;
+               ctx = ccb->ccb_frame->mfr_header.mfh_context;
+               memcpy(ccb->ccb_frame, ioc->mfi_frame.raw,
+                  sizeof(*ccb->ccb_frame));
+               ccb->ccb_frame->mfr_header.mfh_context = ctx;
+               ccb->ccb_frame->mfr_header.mfh_scsi_status = 0;
+               ccb->ccb_frame->mfr_header.mfh_pad0 = 0;
+               ccb->ccb_frame_size =
+                   (sizeof(union mfi_sgl) * ioc->mfi_sge_count) +
+                   ioc->mfi_sgl_off;
+               if (ioc->mfi_sge_count > 0) {
+                       ccb->ccb_sgl = (union mfi_sgl *)
+                           &ccb->ccb_frame->mfr_bytes[ioc->mfi_sgl_off];
+               }
+               if (ccb->ccb_frame->mfr_header.mfh_flags & MFI_FRAME_DIR_READ)
+                       ccb->ccb_direction = MFI_DATA_IN;
+               if (ccb->ccb_frame->mfr_header.mfh_flags & MFI_FRAME_DIR_WRITE)
+                       ccb->ccb_direction = MFI_DATA_OUT;
+               ccb->ccb_len = ccb->ccb_frame->mfr_header.mfh_data_len;
+               if (ccb->ccb_len > MAXPHYS) {
+                       error = ENOMEM;
+                       goto out;
+               }
+               if (ccb->ccb_len &&
+                   (ccb->ccb_direction & (MFI_DATA_IN | MFI_DATA_OUT)) != 0) {
+                       udata = malloc(ccb->ccb_len, M_DEVBUF, M_WAITOK|M_ZERO);
+                       if (udata == NULL) {
+                               error = ENOMEM;
+                               goto out;
+                       }
+                       ccb->ccb_data = udata;
+                       if (ccb->ccb_direction & MFI_DATA_OUT) {
+                               for (i = 0; i < ioc->mfi_sge_count; i++) {
+                                       error = copyin(ioc->mfi_sgl[i].iov_base,
+                                           udata, ioc->mfi_sgl[i].iov_len);
+                                       if (error)
+                                               goto out;
+                                       udata = &udata[
+                                           ioc->mfi_sgl[i].iov_len];
+                               }
+                       }
+                       if (mfi_create_sgl(ccb, BUS_DMA_WAITOK)) {
+                               error = EIO;
+                               goto out;
+                       }
+               }
+               if (ccb->ccb_frame->mfr_header.mfh_cmd == MFI_CMD_PD_SCSI_IO) {
+                       ccb->ccb_frame->mfr_io.mif_sense_addr_lo =
+                           htole32(ccb->ccb_psense);
+                       ccb->ccb_frame->mfr_io.mif_sense_addr_hi = 0;
+               }



Home | Main Index | Thread Index | Old Index