xref: /freebsd/sys/dev/qlxgbe/ql_ioctl.c (revision 0b3105a37d7adcadcb720112fed4dc4e8040be99)
1 /*
2  * Copyright (c) 2013-2016 Qlogic Corporation
3  * All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27 /*
28  * File: ql_ioctl.c
29  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 
35 
36 #include "ql_os.h"
37 #include "ql_hw.h"
38 #include "ql_def.h"
39 #include "ql_inline.h"
40 #include "ql_glbl.h"
41 #include "ql_ioctl.h"
42 
43 static int ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
44 		struct thread *td);
45 
46 static struct cdevsw qla_cdevsw = {
47 	.d_version = D_VERSION,
48 	.d_ioctl = ql_eioctl,
49 	.d_name = "qlcnic",
50 };
51 
52 int
53 ql_make_cdev(qla_host_t *ha)
54 {
55         ha->ioctl_dev = make_dev(&qla_cdevsw,
56 				ha->ifp->if_dunit,
57                                 UID_ROOT,
58                                 GID_WHEEL,
59                                 0600,
60                                 "%s",
61                                 if_name(ha->ifp));
62 
63 	if (ha->ioctl_dev == NULL)
64 		return (-1);
65 
66         ha->ioctl_dev->si_drv1 = ha;
67 
68 	return (0);
69 }
70 
71 void
72 ql_del_cdev(qla_host_t *ha)
73 {
74 	if (ha->ioctl_dev != NULL)
75 		destroy_dev(ha->ioctl_dev);
76 	return;
77 }
78 
79 static int
80 ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
81 	struct thread *td)
82 {
83         qla_host_t *ha;
84         int rval = 0;
85 	device_t pci_dev;
86 	struct ifnet *ifp;
87 
88 	q80_offchip_mem_val_t val;
89 	qla_rd_pci_ids_t *pci_ids;
90 	qla_rd_fw_dump_t *fw_dump;
91         union {
92 		qla_reg_val_t *rv;
93 	        qla_rd_flash_t *rdf;
94 		qla_wr_flash_t *wrf;
95 		qla_erase_flash_t *erf;
96 		qla_offchip_mem_val_t *mem;
97 	} u;
98 
99 
100         if ((ha = (qla_host_t *)dev->si_drv1) == NULL)
101                 return ENXIO;
102 
103 	pci_dev= ha->pci_dev;
104 
105         switch(cmd) {
106 
107         case QLA_RDWR_REG:
108 
109                 u.rv = (qla_reg_val_t *)data;
110 
111                 if (u.rv->direct) {
112                         if (u.rv->rd) {
113                                 u.rv->val = READ_REG32(ha, u.rv->reg);
114                         } else {
115                                 WRITE_REG32(ha, u.rv->reg, u.rv->val);
116                         }
117                 } else {
118                         if ((rval = ql_rdwr_indreg32(ha, u.rv->reg, &u.rv->val,
119                                 u.rv->rd)))
120                                 rval = ENXIO;
121                 }
122                 break;
123 
124         case QLA_RD_FLASH:
125 
126 		if (!ha->hw.flags.fdt_valid) {
127 			rval = EIO;
128 			break;
129 		}
130 
131                 u.rdf = (qla_rd_flash_t *)data;
132                 if ((rval = ql_rd_flash32(ha, u.rdf->off, &u.rdf->data)))
133                         rval = ENXIO;
134                 break;
135 
136 	case QLA_WR_FLASH:
137 
138 		ifp = ha->ifp;
139 
140 		if (ifp == NULL) {
141 			rval = ENXIO;
142 			break;
143 		}
144 
145 		if (ifp->if_drv_flags & (IFF_DRV_OACTIVE | IFF_DRV_RUNNING)) {
146 			rval = ENXIO;
147 			break;
148 		}
149 
150 		if (!ha->hw.flags.fdt_valid) {
151 			rval = EIO;
152 			break;
153 		}
154 
155 		u.wrf = (qla_wr_flash_t *)data;
156 		if ((rval = ql_wr_flash_buffer(ha, u.wrf->off, u.wrf->size,
157 			u.wrf->buffer))) {
158 			printf("flash write failed[%d]\n", rval);
159 			rval = ENXIO;
160 		}
161 		break;
162 
163 	case QLA_ERASE_FLASH:
164 
165 		ifp = ha->ifp;
166 
167 		if (ifp == NULL) {
168 			rval = ENXIO;
169 			break;
170 		}
171 
172 		if (ifp->if_drv_flags & (IFF_DRV_OACTIVE | IFF_DRV_RUNNING)) {
173 			rval = ENXIO;
174 			break;
175 		}
176 
177 		if (!ha->hw.flags.fdt_valid) {
178 			rval = EIO;
179 			break;
180 		}
181 
182 		u.erf = (qla_erase_flash_t *)data;
183 		if ((rval = ql_erase_flash(ha, u.erf->off,
184 			u.erf->size))) {
185 			printf("flash erase failed[%d]\n", rval);
186 			rval = ENXIO;
187 		}
188 		break;
189 
190 	case QLA_RDWR_MS_MEM:
191 		u.mem = (qla_offchip_mem_val_t *)data;
192 
193 		if ((rval = ql_rdwr_offchip_mem(ha, u.mem->off, &val,
194 			u.mem->rd)))
195 			rval = ENXIO;
196 		else {
197 			u.mem->data_lo = val.data_lo;
198 			u.mem->data_hi = val.data_hi;
199 			u.mem->data_ulo = val.data_ulo;
200 			u.mem->data_uhi = val.data_uhi;
201 		}
202 
203 		break;
204 
205 	case QLA_RD_FW_DUMP_SIZE:
206 
207 		if (ha->hw.mdump_init == 0) {
208 			rval = EINVAL;
209 			break;
210 		}
211 
212 		fw_dump = (qla_rd_fw_dump_t *)data;
213 		fw_dump->template_size = ha->hw.dma_buf.minidump.size;
214 		fw_dump->pci_func = ha->pci_func;
215 
216 		break;
217 
218 	case QLA_RD_FW_DUMP:
219 
220 		if (ha->hw.mdump_init == 0) {
221 			rval = EINVAL;
222 			break;
223 		}
224 
225 		fw_dump = (qla_rd_fw_dump_t *)data;
226 
227 		if ((fw_dump->md_template == NULL) ||
228 			(fw_dump->template_size != ha->hw.dma_buf.minidump.size)) {
229 			rval = EINVAL;
230 			break;
231 		}
232 
233 		if ((rval = copyout(ha->hw.dma_buf.minidump.dma_b,
234 			fw_dump->md_template, fw_dump->template_size)))
235 			rval = ENXIO;
236 		break;
237 
238 	case QLA_RD_PCI_IDS:
239 		pci_ids = (qla_rd_pci_ids_t *)data;
240 		pci_ids->ven_id = pci_get_vendor(pci_dev);
241 		pci_ids->dev_id = pci_get_device(pci_dev);
242 		pci_ids->subsys_ven_id = pci_get_subvendor(pci_dev);
243 		pci_ids->subsys_dev_id = pci_get_subdevice(pci_dev);
244 		pci_ids->rev_id = pci_read_config(pci_dev, PCIR_REVID, 1);
245 		break;
246 
247         default:
248                 break;
249         }
250 
251         return rval;
252 }
253 
254