FreeBSD/Linux Kernel Cross Reference
sys/dev/iir/iir_ctrl.c
1 /*
2 * Copyright (c) 2000-03 ICP vortex GmbH
3 * Copyright (c) 2002-03 Intel Corporation
4 * Copyright (c) 2003 Adaptec Inc.
5 * All Rights Reserved
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification, immediately at the beginning of the file.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * iir_ctrl.c: Control functions and /dev entry points for /dev/iir*
34 *
35 * Written by: Achim Leubner <achim_leubner@adaptec.com>
36 * Fixes/Additions: Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com>
37 *
38 * $Id: iir_ctrl.c 1.3 2003/08/26 12:31:15 achim Exp $"
39 */
40
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD: releng/5.2/sys/dev/iir/iir_ctrl.c 120477 2003-09-26 15:36:47Z scottl $");
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/endian.h>
47 #include <sys/malloc.h>
48 #include <sys/kernel.h>
49 #include <sys/uio.h>
50 #include <sys/conf.h>
51 #include <sys/disk.h>
52 #include <sys/stat.h>
53 #include <sys/disklabel.h>
54 #include <machine/bus.h>
55 #include <vm/vm.h>
56 #include <vm/vm_kern.h>
57 #include <vm/vm_extern.h>
58 #include <vm/pmap.h>
59
60 #include <dev/iir/iir.h>
61
62 /* Entry points and other prototypes */
63 static struct gdt_softc *gdt_minor2softc(int minor_no);
64
65 static d_open_t iir_open;
66 static d_close_t iir_close;
67 static d_write_t iir_write;
68 static d_read_t iir_read;
69 static d_ioctl_t iir_ioctl;
70
71 #define CDEV_MAJOR IIR_CDEV_MAJOR
72
73 /* Normally, this is a static structure. But we need it in pci/iir_pci.c */
74 static struct cdevsw iir_cdevsw = {
75 .d_open = iir_open,
76 .d_close = iir_close,
77 .d_read = iir_read,
78 .d_write = iir_write,
79 .d_ioctl = iir_ioctl,
80 .d_name = "iir",
81 .d_maj = CDEV_MAJOR,
82 };
83
84 /*
85 static int iir_devsw_installed = 0;
86 */
87 #ifndef SDEV_PER_HBA
88 static int sdev_made = 0;
89 #endif
90 extern int gdt_cnt;
91 extern char ostype[];
92 extern char osrelease[];
93 extern gdt_statist_t gdt_stat;
94
95 /*
96 * Given a controller number,
97 * make a special device and return the dev_t
98 */
99 dev_t
100 gdt_make_dev(int unit)
101 {
102 dev_t dev;
103
104 #ifdef SDEV_PER_HBA
105 dev = make_dev(&iir_cdevsw, hba2minor(unit), UID_ROOT, GID_OPERATOR,
106 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, "iir%d", unit);
107 #else
108 if (sdev_made)
109 return (0);
110 dev = make_dev(&iir_cdevsw, 0, UID_ROOT, GID_OPERATOR,
111 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, "iir");
112 sdev_made = 1;
113 #endif
114 return (dev);
115 }
116
117 void
118 gdt_destroy_dev(dev_t dev)
119 {
120 if (dev != NULL)
121 destroy_dev(dev);
122 }
123
124 /*
125 * Given a minor device number,
126 * return the pointer to its softc structure
127 */
128 static struct gdt_softc *
129 gdt_minor2softc(int minor_no)
130 {
131 struct gdt_softc *gdt;
132 int hanum;
133
134 #ifdef SDEV_PER_HBA
135 hanum = minor2hba(minor_no);
136 #else
137 hanum = minor_no;
138 #endif
139
140 for (gdt = TAILQ_FIRST(&gdt_softcs);
141 gdt != NULL && gdt->sc_hanum != hanum;
142 gdt = TAILQ_NEXT(gdt, links));
143
144 return (gdt);
145 }
146
147 static int
148 iir_open(dev_t dev, int flags, int fmt, d_thread_t * p)
149 {
150 GDT_DPRINTF(GDT_D_DEBUG, ("iir_open()\n"));
151
152 #ifdef SDEV_PER_HBA
153 int minor_no;
154 struct gdt_softc *gdt;
155
156 minor_no = minor(dev);
157 gdt = gdt_minor2softc(minor_no);
158 if (gdt == NULL)
159 return (ENXIO);
160 #endif
161
162 return (0);
163 }
164
165 static int
166 iir_close(dev_t dev, int flags, int fmt, d_thread_t * p)
167 {
168 GDT_DPRINTF(GDT_D_DEBUG, ("iir_close()\n"));
169
170 #ifdef SDEV_PER_HBA
171 int minor_no;
172 struct gdt_softc *gdt;
173
174 minor_no = minor(dev);
175 gdt = gdt_minor2softc(minor_no);
176 if (gdt == NULL)
177 return (ENXIO);
178 #endif
179
180 return (0);
181 }
182
183 static int
184 iir_write(dev_t dev, struct uio * uio, int ioflag)
185 {
186 GDT_DPRINTF(GDT_D_DEBUG, ("iir_write()\n"));
187
188 #ifdef SDEV_PER_HBA
189 int minor_no;
190 struct gdt_softc *gdt;
191
192 minor_no = minor(dev);
193 gdt = gdt_minor2softc(minor_no);
194 if (gdt == NULL)
195 return (ENXIO);
196 #endif
197
198 return (0);
199 }
200
201 static int
202 iir_read(dev_t dev, struct uio * uio, int ioflag)
203 {
204 GDT_DPRINTF(GDT_D_DEBUG, ("iir_read()\n"));
205
206 #ifdef SDEV_PER_HBA
207 int minor_no;
208 struct gdt_softc *gdt;
209
210 minor_no = minor(dev);
211 gdt = gdt_minor2softc(minor_no);
212 if (gdt == NULL)
213 return (ENXIO);
214 #endif
215
216 return (0);
217 }
218
219 /**
220 * This is the control syscall interface.
221 * It should be binary compatible with UnixWare,
222 * if not totally syntatically so.
223 */
224
225 static int
226 iir_ioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, d_thread_t * p)
227 {
228 GDT_DPRINTF(GDT_D_DEBUG, ("iir_ioctl() cmd 0x%lx\n",cmd));
229
230 #ifdef SDEV_PER_HBA
231 int minor_no;
232 struct gdt_softc *gdt;
233
234 minor_no = minor(dev);
235 gdt = gdt_minor2softc(minor_no);
236 if (gdt == NULL)
237 return (ENXIO);
238 #endif
239 ++gdt_stat.io_count_act;
240 if (gdt_stat.io_count_act > gdt_stat.io_count_max)
241 gdt_stat.io_count_max = gdt_stat.io_count_act;
242
243 switch (cmd) {
244 case GDT_IOCTL_GENERAL:
245 {
246 gdt_ucmd_t *ucmd;
247 struct gdt_softc *gdt;
248 int lock;
249
250 ucmd = (gdt_ucmd_t *)cmdarg;
251 gdt = gdt_minor2softc(ucmd->io_node);
252 if (gdt == NULL)
253 return (ENXIO);
254 lock = splcam();
255 TAILQ_INSERT_TAIL(&gdt->sc_ucmd_queue, ucmd, links);
256 ucmd->complete_flag = FALSE;
257 splx(lock);
258 gdt_next(gdt);
259 if (!ucmd->complete_flag)
260 (void) tsleep((void *)ucmd, PCATCH | PRIBIO, "iirucw", 0);
261 break;
262 }
263
264 case GDT_IOCTL_DRVERS:
265 *(int *)cmdarg =
266 (IIR_DRIVER_VERSION << 8) | IIR_DRIVER_SUBVERSION;
267 break;
268
269 case GDT_IOCTL_CTRTYPE:
270 {
271 gdt_ctrt_t *p;
272 struct gdt_softc *gdt;
273
274 p = (gdt_ctrt_t *)cmdarg;
275 gdt = gdt_minor2softc(p->io_node);
276 if (gdt == NULL)
277 return (ENXIO);
278 /* only RP controllers */
279 p->ext_type = 0x6000 | gdt->sc_device;
280 if (gdt->sc_vendor == INTEL_VENDOR_ID) {
281 p->oem_id = OEM_ID_INTEL;
282 p->type = 0xfd;
283 /* new -> subdevice into ext_type */
284 if (gdt->sc_device >= 0x600)
285 p->ext_type = 0x6000 | gdt->sc_subdevice;
286 } else {
287 p->oem_id = OEM_ID_ICP;
288 p->type = 0xfe;
289 /* new -> subdevice into ext_type */
290 if (gdt->sc_device >= 0x300)
291 p->ext_type = 0x6000 | gdt->sc_subdevice;
292 }
293 p->info = (gdt->sc_bus << 8) | (gdt->sc_slot << 3);
294 p->device_id = gdt->sc_device;
295 p->sub_device_id = gdt->sc_subdevice;
296 break;
297 }
298
299 case GDT_IOCTL_OSVERS:
300 {
301 gdt_osv_t *p;
302
303 p = (gdt_osv_t *)cmdarg;
304 p->oscode = 10;
305 p->version = osrelease[0] - '';
306 if (osrelease[1] == '.')
307 p->subversion = osrelease[2] - '';
308 else
309 p->subversion = 0;
310 if (osrelease[3] == '.')
311 p->revision = osrelease[4] - '';
312 else
313 p->revision = 0;
314 strcpy(p->name, ostype);
315 break;
316 }
317
318 case GDT_IOCTL_CTRCNT:
319 *(int *)cmdarg = gdt_cnt;
320 break;
321
322 case GDT_IOCTL_EVENT:
323 {
324 gdt_event_t *p;
325 int lock;
326
327 p = (gdt_event_t *)cmdarg;
328 if (p->erase == 0xff) {
329 if (p->dvr.event_source == GDT_ES_TEST)
330 p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.test);
331 else if (p->dvr.event_source == GDT_ES_DRIVER)
332 p->dvr.event_data.size= sizeof(p->dvr.event_data.eu.driver);
333 else if (p->dvr.event_source == GDT_ES_SYNC)
334 p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.sync);
335 else
336 p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.async);
337 lock = splcam();
338 gdt_store_event(p->dvr.event_source, p->dvr.event_idx,
339 &p->dvr.event_data);
340 splx(lock);
341 } else if (p->erase == 0xfe) {
342 lock = splcam();
343 gdt_clear_events();
344 splx(lock);
345 } else if (p->erase == 0) {
346 p->handle = gdt_read_event(p->handle, &p->dvr);
347 } else {
348 gdt_readapp_event((u_int8_t)p->erase, &p->dvr);
349 }
350 break;
351 }
352
353 case GDT_IOCTL_STATIST:
354 {
355 gdt_statist_t *p;
356
357 p = (gdt_statist_t *)cmdarg;
358 bcopy(&gdt_stat, p, sizeof(gdt_statist_t));
359 break;
360 }
361
362 default:
363 break;
364 }
365
366 --gdt_stat.io_count_act;
367 return (0);
368 }
369
370 /*
371 static void
372 iir_drvinit(void *unused)
373 {
374 GDT_DPRINTF(GDT_D_DEBUG, ("iir_drvinit()\n"));
375
376 if (!iir_devsw_installed) {
377 cdevsw_add(&iir_cdevsw);
378 iir_devsw_installed = 1;
379 }
380 }
381
382 SYSINIT(iir_dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, iir_drvinit, NULL)
383 */
Cache object: 06136ae41165653c24e82bbff3a25131
|