iir_ctrl.c revision 330897
1/*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2000-03 ICP vortex GmbH 5 * Copyright (c) 2002-03 Intel Corporation 6 * Copyright (c) 2003 Adaptec Inc. 7 * All Rights Reserved 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions, and the following disclaimer, 14 * without modification, immediately at the beginning of the file. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34/* 35 * iir_ctrl.c: Control functions and /dev entry points for /dev/iir* 36 * 37 * Written by: Achim Leubner <achim_leubner@adaptec.com> 38 * Fixes/Additions: Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com> 39 * 40 * $Id: iir_ctrl.c 1.3 2003/08/26 12:31:15 achim Exp $" 41 */ 42 43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD: stable/11/sys/dev/iir/iir_ctrl.c 330897 2018-03-14 03:19:51Z eadler $"); 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/bus.h> 49#include <sys/endian.h> 50#include <sys/malloc.h> 51#include <sys/kernel.h> 52#include <sys/uio.h> 53#include <sys/conf.h> 54#include <sys/disk.h> 55#include <sys/stat.h> 56#include <sys/disklabel.h> 57#include <sys/sysctl.h> 58#include <sys/sx.h> 59#include <machine/bus.h> 60 61#include <dev/iir/iir.h> 62 63/* Entry points and other prototypes */ 64static struct gdt_softc *gdt_minor2softc(struct cdev *dev, int minor_no); 65 66static d_open_t iir_open; 67static d_close_t iir_close; 68static d_write_t iir_write; 69static d_read_t iir_read; 70static d_ioctl_t iir_ioctl; 71 72/* Normally, this is a static structure. But we need it in pci/iir_pci.c */ 73static struct cdevsw iir_cdevsw = { 74 .d_version = D_VERSION, 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}; 82 83#ifndef SDEV_PER_HBA 84static int sdev_made = 0; 85static struct sx sdev_lock; 86SX_SYSINIT(iir_sdev_lock, &sdev_lock, "iir sdev"); 87#endif 88extern int gdt_cnt; 89extern gdt_statist_t gdt_stat; 90 91/* 92 * Given a controller number, 93 * make a special device and return the dev_t 94 */ 95struct cdev * 96gdt_make_dev(struct gdt_softc *gdt) 97{ 98 struct cdev *dev; 99 100#ifdef SDEV_PER_HBA 101 dev = make_dev(&iir_cdevsw, 0, UID_ROOT, GID_OPERATOR, 102 S_IRUSR | S_IWUSR, "iir%d", unit); 103 dev->si_drv1 = gdt; 104#else 105 sx_xlock(&sdev_lock); 106 if (sdev_made) 107 return (NULL); 108 dev = make_dev(&iir_cdevsw, 0, UID_ROOT, GID_OPERATOR, 109 S_IRUSR | S_IWUSR, "iir"); 110 sdev_made = 1; 111 sx_xunlock(&sdev_lock); 112#endif 113 return (dev); 114} 115 116void 117gdt_destroy_dev(struct cdev *dev) 118{ 119 if (dev != NULL) 120 destroy_dev(dev); 121} 122 123/* 124 * Given a minor device number, 125 * return the pointer to its softc structure 126 */ 127static struct gdt_softc * 128gdt_minor2softc(struct cdev *dev, int minor_no) 129{ 130#ifdef SDEV_PER_HBA 131 132 return (dev->si_drv1); 133#else 134 devclass_t dc; 135 device_t child; 136 137 dc = devclass_find("iir"); 138 if (dc == NULL) 139 return (NULL); 140 child = devclass_get_device(dc, minor_no); 141 if (child == NULL) 142 return (NULL); 143 return (device_get_softc(child)); 144#endif 145} 146 147static int 148iir_open(struct cdev *dev, int flags, int fmt, struct thread * p) 149{ 150 GDT_DPRINTF(GDT_D_DEBUG, ("iir_open()\n")); 151 152 return (0); 153} 154 155static int 156iir_close(struct cdev *dev, int flags, int fmt, struct thread * p) 157{ 158 GDT_DPRINTF(GDT_D_DEBUG, ("iir_close()\n")); 159 160 return (0); 161} 162 163static int 164iir_write(struct cdev *dev, struct uio * uio, int ioflag) 165{ 166 GDT_DPRINTF(GDT_D_DEBUG, ("iir_write()\n")); 167 168 return (0); 169} 170 171static int 172iir_read(struct cdev *dev, struct uio * uio, int ioflag) 173{ 174 GDT_DPRINTF(GDT_D_DEBUG, ("iir_read()\n")); 175 176 return (0); 177} 178 179/** 180 * This is the control syscall interface. 181 * It should be binary compatible with UnixWare, 182 * if not totally syntatically so. 183 */ 184 185static int 186iir_ioctl(struct cdev *dev, u_long cmd, caddr_t cmdarg, int flags, struct thread * p) 187{ 188 GDT_DPRINTF(GDT_D_DEBUG, ("iir_ioctl() cmd 0x%lx\n",cmd)); 189 190 ++gdt_stat.io_count_act; 191 if (gdt_stat.io_count_act > gdt_stat.io_count_max) 192 gdt_stat.io_count_max = gdt_stat.io_count_act; 193 194 switch (cmd) { 195 case GDT_IOCTL_GENERAL: 196 { 197 gdt_ucmd_t *ucmd; 198 struct gdt_softc *gdt; 199 200 ucmd = (gdt_ucmd_t *)cmdarg; 201 gdt = gdt_minor2softc(dev, ucmd->io_node); 202 if (gdt == NULL) 203 return (ENXIO); 204 mtx_lock(&gdt->sc_lock); 205 TAILQ_INSERT_TAIL(&gdt->sc_ucmd_queue, ucmd, links); 206 ucmd->complete_flag = FALSE; 207 gdt_next(gdt); 208 if (!ucmd->complete_flag) 209 (void) mtx_sleep(ucmd, &gdt->sc_lock, PCATCH | PRIBIO, "iirucw", 210 0); 211 mtx_unlock(&gdt->sc_lock); 212 break; 213 } 214 215 case GDT_IOCTL_DRVERS: 216 case GDT_IOCTL_DRVERS_OLD: 217 *(int *)cmdarg = 218 (IIR_DRIVER_VERSION << 8) | IIR_DRIVER_SUBVERSION; 219 break; 220 221 case GDT_IOCTL_CTRTYPE: 222 case GDT_IOCTL_CTRTYPE_OLD: 223 { 224 gdt_ctrt_t *p; 225 struct gdt_softc *gdt; 226 227 p = (gdt_ctrt_t *)cmdarg; 228 gdt = gdt_minor2softc(dev, p->io_node); 229 if (gdt == NULL) 230 return (ENXIO); 231 /* only RP controllers */ 232 p->ext_type = 0x6000 | gdt->sc_device; 233 if (gdt->sc_vendor == INTEL_VENDOR_ID_IIR) { 234 p->oem_id = OEM_ID_INTEL; 235 p->type = 0xfd; 236 /* new -> subdevice into ext_type */ 237 if (gdt->sc_device >= 0x600) 238 p->ext_type = 0x6000 | gdt->sc_subdevice; 239 } else { 240 p->oem_id = OEM_ID_ICP; 241 p->type = 0xfe; 242 /* new -> subdevice into ext_type */ 243 if (gdt->sc_device >= 0x300) 244 p->ext_type = 0x6000 | gdt->sc_subdevice; 245 } 246 p->info = (gdt->sc_bus << 8) | (gdt->sc_slot << 3); 247 p->device_id = gdt->sc_device; 248 p->sub_device_id = gdt->sc_subdevice; 249 break; 250 } 251 252 case GDT_IOCTL_OSVERS: 253 { 254 gdt_osv_t *p; 255 256 p = (gdt_osv_t *)cmdarg; 257 p->oscode = 10; 258 p->version = osreldate / 100000; 259 p->subversion = osreldate / 1000 % 100; 260 p->revision = 0; 261 strcpy(p->name, ostype); 262 break; 263 } 264 265 case GDT_IOCTL_CTRCNT: 266 *(int *)cmdarg = gdt_cnt; 267 break; 268 269 case GDT_IOCTL_EVENT: 270 { 271 gdt_event_t *p; 272 273 p = (gdt_event_t *)cmdarg; 274 if (p->erase == 0xff) { 275 if (p->dvr.event_source == GDT_ES_TEST) 276 p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.test); 277 else if (p->dvr.event_source == GDT_ES_DRIVER) 278 p->dvr.event_data.size= sizeof(p->dvr.event_data.eu.driver); 279 else if (p->dvr.event_source == GDT_ES_SYNC) 280 p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.sync); 281 else 282 p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.async); 283 gdt_store_event(p->dvr.event_source, p->dvr.event_idx, 284 &p->dvr.event_data); 285 } else if (p->erase == 0xfe) { 286 gdt_clear_events(); 287 } else if (p->erase == 0) { 288 p->handle = gdt_read_event(p->handle, &p->dvr); 289 } else { 290 gdt_readapp_event((u_int8_t)p->erase, &p->dvr); 291 } 292 break; 293 } 294 295 case GDT_IOCTL_STATIST: 296 { 297 gdt_statist_t *p; 298 299 p = (gdt_statist_t *)cmdarg; 300 bcopy(&gdt_stat, p, sizeof(gdt_statist_t)); 301 break; 302 } 303 304 default: 305 break; 306 } 307 308 --gdt_stat.io_count_act; 309 return (0); 310} 311