1252206Sdavidcs/*
2252206Sdavidcs * Copyright (c) 2013-2014 Qlogic Corporation
3252206Sdavidcs * All rights reserved.
4252206Sdavidcs *
5252206Sdavidcs *  Redistribution and use in source and binary forms, with or without
6252206Sdavidcs *  modification, are permitted provided that the following conditions
7252206Sdavidcs *  are met:
8252206Sdavidcs *
9252206Sdavidcs *  1. Redistributions of source code must retain the above copyright
10252206Sdavidcs *     notice, this list of conditions and the following disclaimer.
11252206Sdavidcs *  2. Redistributions in binary form must reproduce the above copyright
12252206Sdavidcs *     notice, this list of conditions and the following disclaimer in the
13252206Sdavidcs *     documentation and/or other materials provided with the distribution.
14252206Sdavidcs *
15252206Sdavidcs *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16252206Sdavidcs *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17252206Sdavidcs *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18252206Sdavidcs *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19252206Sdavidcs *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20252206Sdavidcs *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21252206Sdavidcs *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22252206Sdavidcs *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23252206Sdavidcs *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24252206Sdavidcs *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25252206Sdavidcs *  POSSIBILITY OF SUCH DAMAGE.
26252206Sdavidcs */
27252206Sdavidcs/*
28252206Sdavidcs * File: qls_ioctl.c
29252206Sdavidcs * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
30252206Sdavidcs */
31252206Sdavidcs#include <sys/cdefs.h>
32252206Sdavidcs__FBSDID("$FreeBSD$");
33252206Sdavidcs
34252206Sdavidcs
35252206Sdavidcs#include "qls_os.h"
36252206Sdavidcs#include "qls_hw.h"
37252206Sdavidcs#include "qls_def.h"
38252206Sdavidcs#include "qls_inline.h"
39252206Sdavidcs#include "qls_glbl.h"
40252206Sdavidcs#include "qls_ioctl.h"
41252206Sdavidcs#include "qls_dump.h"
42252206Sdavidcsextern qls_mpi_coredump_t ql_mpi_coredump;
43252206Sdavidcs
44252206Sdavidcsstatic int qls_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
45252206Sdavidcs		struct thread *td);
46252206Sdavidcs
47252206Sdavidcsstatic struct cdevsw qla_cdevsw = {
48252206Sdavidcs	.d_version = D_VERSION,
49252206Sdavidcs	.d_ioctl = qls_eioctl,
50252206Sdavidcs	.d_name = "qlxge",
51252206Sdavidcs};
52252206Sdavidcs
53252206Sdavidcsint
54252206Sdavidcsqls_make_cdev(qla_host_t *ha)
55252206Sdavidcs{
56252206Sdavidcs        ha->ioctl_dev = make_dev(&qla_cdevsw,
57252206Sdavidcs				ha->ifp->if_dunit,
58252206Sdavidcs                                UID_ROOT,
59252206Sdavidcs                                GID_WHEEL,
60252206Sdavidcs                                0600,
61252206Sdavidcs                                "%s",
62252206Sdavidcs                                if_name(ha->ifp));
63252206Sdavidcs
64252206Sdavidcs	if (ha->ioctl_dev == NULL)
65252206Sdavidcs		return (-1);
66252206Sdavidcs
67252206Sdavidcs        ha->ioctl_dev->si_drv1 = ha;
68252206Sdavidcs
69252206Sdavidcs	return (0);
70252206Sdavidcs}
71252206Sdavidcs
72252206Sdavidcsvoid
73252206Sdavidcsqls_del_cdev(qla_host_t *ha)
74252206Sdavidcs{
75252206Sdavidcs	if (ha->ioctl_dev != NULL)
76252206Sdavidcs		destroy_dev(ha->ioctl_dev);
77252206Sdavidcs	return;
78252206Sdavidcs}
79252206Sdavidcs
80252206Sdavidcsstatic int
81252206Sdavidcsqls_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
82252206Sdavidcs        struct thread *td)
83252206Sdavidcs{
84252206Sdavidcs        qla_host_t *ha;
85252206Sdavidcs        int rval = 0;
86252206Sdavidcs	device_t pci_dev;
87252206Sdavidcs
88252206Sdavidcs	qls_mpi_dump_t *mpi_dump;
89252206Sdavidcs
90252206Sdavidcs        if ((ha = (qla_host_t *)dev->si_drv1) == NULL)
91252206Sdavidcs                return ENXIO;
92252206Sdavidcs
93252206Sdavidcs	pci_dev= ha->pci_dev;
94252206Sdavidcs
95252206Sdavidcs        switch(cmd) {
96252206Sdavidcs
97252206Sdavidcs	case QLA_MPI_DUMP:
98252206Sdavidcs		mpi_dump = (qls_mpi_dump_t *)data;
99252206Sdavidcs
100252206Sdavidcs		if (mpi_dump->size == 0) {
101252206Sdavidcs			mpi_dump->size = sizeof (qls_mpi_coredump_t);
102252206Sdavidcs		} else {
103258457Sdavidcs			if ((mpi_dump->size != sizeof (qls_mpi_coredump_t)) ||
104258457Sdavidcs				(mpi_dump->dbuf == NULL))
105252206Sdavidcs				rval = EINVAL;
106252206Sdavidcs			else {
107258457Sdavidcs				if (qls_mpi_core_dump(ha) == 0) {
108258457Sdavidcs					rval = copyout(&ql_mpi_coredump,
109258457Sdavidcs							mpi_dump->dbuf,
110258457Sdavidcs							mpi_dump->size);
111258457Sdavidcs				} else
112258457Sdavidcs					rval = ENXIO;
113252206Sdavidcs
114252206Sdavidcs				if (rval) {
115252206Sdavidcs					device_printf(ha->pci_dev,
116252206Sdavidcs						"%s: mpidump failed[%d]\n",
117252206Sdavidcs						__func__, rval);
118252206Sdavidcs				}
119252206Sdavidcs			}
120252206Sdavidcs
121252206Sdavidcs		}
122252206Sdavidcs
123252206Sdavidcs		break;
124252206Sdavidcs        default:
125252206Sdavidcs                break;
126252206Sdavidcs        }
127252206Sdavidcs
128252206Sdavidcs        return rval;
129252206Sdavidcs}
130252206Sdavidcs
131