1139749Simp/*- 2120477Sscottl * Copyright (c) 2000-03 ICP vortex GmbH 3120477Sscottl * Copyright (c) 2002-03 Intel Corporation 4120477Sscottl * Copyright (c) 2003 Adaptec Inc. 589580Smsmith * All Rights Reserved 689580Smsmith * 789580Smsmith * Redistribution and use in source and binary forms, with or without 889580Smsmith * modification, are permitted provided that the following conditions 989580Smsmith * are met: 1089580Smsmith * 1. Redistributions of source code must retain the above copyright 1189580Smsmith * notice, this list of conditions, and the following disclaimer, 1289580Smsmith * without modification, immediately at the beginning of the file. 1389580Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1489580Smsmith * notice, this list of conditions and the following disclaimer in the 1589580Smsmith * documentation and/or other materials provided with the distribution. 1689580Smsmith * 3. The name of the author may not be used to endorse or promote products 1789580Smsmith * derived from this software without specific prior written permission. 1889580Smsmith * 1989580Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2089580Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2189580Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2289580Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2389580Smsmith * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2489580Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2589580Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2689580Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2789580Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2889580Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2989580Smsmith * SUCH DAMAGE. 3089580Smsmith */ 3189580Smsmith 3289580Smsmith/* 3389580Smsmith * iir_ctrl.c: Control functions and /dev entry points for /dev/iir* 3489580Smsmith * 35120477Sscottl * Written by: Achim Leubner <achim_leubner@adaptec.com> 3689580Smsmith * Fixes/Additions: Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com> 3789580Smsmith * 38120477Sscottl * $Id: iir_ctrl.c 1.3 2003/08/26 12:31:15 achim Exp $" 3989580Smsmith */ 4089580Smsmith 41119418Sobrien#include <sys/cdefs.h> 42119418Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/dev/iir/iir_ctrl.c 275975 2014-12-21 01:39:21Z smh $"); 4389580Smsmith 4489580Smsmith#include <sys/param.h> 4589580Smsmith#include <sys/systm.h> 46275975Ssmh#include <sys/bus.h> 4795533Smike#include <sys/endian.h> 4889580Smsmith#include <sys/malloc.h> 4989580Smsmith#include <sys/kernel.h> 5089580Smsmith#include <sys/uio.h> 5189580Smsmith#include <sys/conf.h> 52114001Sscottl#include <sys/disk.h> 5389580Smsmith#include <sys/stat.h> 54114001Sscottl#include <sys/disklabel.h> 55200045Smarcel#include <sys/sysctl.h> 56275975Ssmh#include <sys/sx.h> 5789580Smsmith#include <machine/bus.h> 5889580Smsmith 5989580Smsmith#include <dev/iir/iir.h> 6089580Smsmith 6189580Smsmith/* Entry points and other prototypes */ 62275975Ssmhstatic struct gdt_softc *gdt_minor2softc(struct cdev *dev, int minor_no); 6389580Smsmith 6489580Smsmithstatic d_open_t iir_open; 6589580Smsmithstatic d_close_t iir_close; 6689580Smsmithstatic d_write_t iir_write; 6789580Smsmithstatic d_read_t iir_read; 6889580Smsmithstatic d_ioctl_t iir_ioctl; 6989580Smsmith 7089580Smsmith/* Normally, this is a static structure. But we need it in pci/iir_pci.c */ 7189580Smsmithstatic struct cdevsw iir_cdevsw = { 72126080Sphk .d_version = D_VERSION, 73111815Sphk .d_open = iir_open, 74111815Sphk .d_close = iir_close, 75111815Sphk .d_read = iir_read, 76111815Sphk .d_write = iir_write, 77111815Sphk .d_ioctl = iir_ioctl, 78111815Sphk .d_name = "iir", 7989580Smsmith}; 8089580Smsmith 8189580Smsmith#ifndef SDEV_PER_HBA 8289580Smsmithstatic int sdev_made = 0; 83275975Ssmhstatic struct sx sdev_lock; 84275975SsmhSX_SYSINIT(iir_sdev_lock, &sdev_lock, "iir sdev"); 8589580Smsmith#endif 8689580Smsmithextern int gdt_cnt; 8789580Smsmithextern gdt_statist_t gdt_stat; 8889580Smsmith 8989580Smsmith/* 9089580Smsmith * Given a controller number, 9189580Smsmith * make a special device and return the dev_t 9289580Smsmith */ 93130585Sphkstruct cdev * 94275975Ssmhgdt_make_dev(struct gdt_softc *gdt) 9589580Smsmith{ 96130585Sphk struct cdev *dev; 9789580Smsmith 9889580Smsmith#ifdef SDEV_PER_HBA 99275975Ssmh dev = make_dev(&iir_cdevsw, 0, UID_ROOT, GID_OPERATOR, 100145947Scperciva S_IRUSR | S_IWUSR, "iir%d", unit); 101275975Ssmh dev->si_drv1 = gdt; 10289580Smsmith#else 103275975Ssmh sx_xlock(&sdev_lock); 10489580Smsmith if (sdev_made) 105275975Ssmh return (NULL); 10689580Smsmith dev = make_dev(&iir_cdevsw, 0, UID_ROOT, GID_OPERATOR, 107145947Scperciva S_IRUSR | S_IWUSR, "iir"); 10889580Smsmith sdev_made = 1; 109275975Ssmh sx_xunlock(&sdev_lock); 11089580Smsmith#endif 11189580Smsmith return (dev); 11289580Smsmith} 11389580Smsmith 11489580Smsmithvoid 115130585Sphkgdt_destroy_dev(struct cdev *dev) 11689580Smsmith{ 11789580Smsmith if (dev != NULL) 11889580Smsmith destroy_dev(dev); 11989580Smsmith} 12089580Smsmith 12189580Smsmith/* 12289580Smsmith * Given a minor device number, 12389580Smsmith * return the pointer to its softc structure 12489580Smsmith */ 12589580Smsmithstatic struct gdt_softc * 126275975Ssmhgdt_minor2softc(struct cdev *dev, int minor_no) 12789580Smsmith{ 128275975Ssmh#ifdef SDEV_PER_HBA 12989580Smsmith 130275975Ssmh return (dev->si_drv1); 13189580Smsmith#else 132275975Ssmh devclass_t dc; 133275975Ssmh device_t child; 134275975Ssmh 135275975Ssmh dc = devclass_find("iir"); 136275975Ssmh if (dc == NULL) 137275975Ssmh return (NULL); 138275975Ssmh child = devclass_get_device(dc, minor_no); 139275975Ssmh if (child == NULL) 140275975Ssmh return (NULL); 141275975Ssmh return (device_get_softc(child)); 14289580Smsmith#endif 14389580Smsmith} 14489580Smsmith 14589580Smsmithstatic int 146192450Simpiir_open(struct cdev *dev, int flags, int fmt, struct thread * p) 14789580Smsmith{ 14889580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_open()\n")); 14989580Smsmith 15089580Smsmith return (0); 15189580Smsmith} 15289580Smsmith 15389580Smsmithstatic int 154192450Simpiir_close(struct cdev *dev, int flags, int fmt, struct thread * p) 15589580Smsmith{ 15689580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_close()\n")); 15789580Smsmith 15889580Smsmith return (0); 15989580Smsmith} 16089580Smsmith 16189580Smsmithstatic int 162130585Sphkiir_write(struct cdev *dev, struct uio * uio, int ioflag) 16389580Smsmith{ 16489580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_write()\n")); 16589580Smsmith 16689580Smsmith return (0); 16789580Smsmith} 16889580Smsmith 16989580Smsmithstatic int 170130585Sphkiir_read(struct cdev *dev, struct uio * uio, int ioflag) 17189580Smsmith{ 17289580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_read()\n")); 17389580Smsmith 17489580Smsmith return (0); 17589580Smsmith} 17689580Smsmith 17789580Smsmith/** 17889580Smsmith * This is the control syscall interface. 17989580Smsmith * It should be binary compatible with UnixWare, 18089580Smsmith * if not totally syntatically so. 18189580Smsmith */ 18289580Smsmith 18389580Smsmithstatic int 184192450Simpiir_ioctl(struct cdev *dev, u_long cmd, caddr_t cmdarg, int flags, struct thread * p) 18589580Smsmith{ 18689580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_ioctl() cmd 0x%lx\n",cmd)); 18789580Smsmith 18889580Smsmith ++gdt_stat.io_count_act; 18989580Smsmith if (gdt_stat.io_count_act > gdt_stat.io_count_max) 19089580Smsmith gdt_stat.io_count_max = gdt_stat.io_count_act; 19189580Smsmith 19289580Smsmith switch (cmd) { 19389580Smsmith case GDT_IOCTL_GENERAL: 19489580Smsmith { 19589580Smsmith gdt_ucmd_t *ucmd; 19689580Smsmith struct gdt_softc *gdt; 19789580Smsmith 19889580Smsmith ucmd = (gdt_ucmd_t *)cmdarg; 199275975Ssmh gdt = gdt_minor2softc(dev, ucmd->io_node); 20089580Smsmith if (gdt == NULL) 20189580Smsmith return (ENXIO); 202275975Ssmh mtx_lock(&gdt->sc_lock); 20389580Smsmith TAILQ_INSERT_TAIL(&gdt->sc_ucmd_queue, ucmd, links); 20489580Smsmith ucmd->complete_flag = FALSE; 20589580Smsmith gdt_next(gdt); 20689580Smsmith if (!ucmd->complete_flag) 207275975Ssmh (void) mtx_sleep(ucmd, &gdt->sc_lock, PCATCH | PRIBIO, "iirucw", 208275975Ssmh 0); 209275975Ssmh mtx_unlock(&gdt->sc_lock); 21089580Smsmith break; 21189580Smsmith } 21289580Smsmith 21389580Smsmith case GDT_IOCTL_DRVERS: 214129449Sscottl case GDT_IOCTL_DRVERS_OLD: 21589580Smsmith *(int *)cmdarg = 21689580Smsmith (IIR_DRIVER_VERSION << 8) | IIR_DRIVER_SUBVERSION; 21789580Smsmith break; 21889580Smsmith 21989580Smsmith case GDT_IOCTL_CTRTYPE: 220129449Sscottl case GDT_IOCTL_CTRTYPE_OLD: 22189580Smsmith { 22289580Smsmith gdt_ctrt_t *p; 22389580Smsmith struct gdt_softc *gdt; 22489580Smsmith 22589580Smsmith p = (gdt_ctrt_t *)cmdarg; 226275975Ssmh gdt = gdt_minor2softc(dev, p->io_node); 22789580Smsmith if (gdt == NULL) 22889580Smsmith return (ENXIO); 229120477Sscottl /* only RP controllers */ 230120477Sscottl p->ext_type = 0x6000 | gdt->sc_device; 231254379Sjkim if (gdt->sc_vendor == INTEL_VENDOR_ID_IIR) { 232120477Sscottl p->oem_id = OEM_ID_INTEL; 233120477Sscottl p->type = 0xfd; 234120477Sscottl /* new -> subdevice into ext_type */ 235120477Sscottl if (gdt->sc_device >= 0x600) 236120477Sscottl p->ext_type = 0x6000 | gdt->sc_subdevice; 237120477Sscottl } else { 238120477Sscottl p->oem_id = OEM_ID_ICP; 239120477Sscottl p->type = 0xfe; 240120477Sscottl /* new -> subdevice into ext_type */ 241120477Sscottl if (gdt->sc_device >= 0x300) 242120477Sscottl p->ext_type = 0x6000 | gdt->sc_subdevice; 243120477Sscottl } 24489580Smsmith p->info = (gdt->sc_bus << 8) | (gdt->sc_slot << 3); 24589580Smsmith p->device_id = gdt->sc_device; 24689580Smsmith p->sub_device_id = gdt->sc_subdevice; 24789580Smsmith break; 24889580Smsmith } 24989580Smsmith 25089580Smsmith case GDT_IOCTL_OSVERS: 25189580Smsmith { 25289580Smsmith gdt_osv_t *p; 25389580Smsmith 25489580Smsmith p = (gdt_osv_t *)cmdarg; 25589580Smsmith p->oscode = 10; 256275975Ssmh p->version = osreldate / 100000; 257275975Ssmh p->subversion = osreldate / 1000 % 100; 258275975Ssmh p->revision = 0; 25989580Smsmith strcpy(p->name, ostype); 26089580Smsmith break; 26189580Smsmith } 26289580Smsmith 26389580Smsmith case GDT_IOCTL_CTRCNT: 26489580Smsmith *(int *)cmdarg = gdt_cnt; 26589580Smsmith break; 26689580Smsmith 26789580Smsmith case GDT_IOCTL_EVENT: 26889580Smsmith { 26989580Smsmith gdt_event_t *p; 27089580Smsmith 27189580Smsmith p = (gdt_event_t *)cmdarg; 27289580Smsmith if (p->erase == 0xff) { 27389580Smsmith if (p->dvr.event_source == GDT_ES_TEST) 27489580Smsmith p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.test); 27589580Smsmith else if (p->dvr.event_source == GDT_ES_DRIVER) 27689580Smsmith p->dvr.event_data.size= sizeof(p->dvr.event_data.eu.driver); 27789580Smsmith else if (p->dvr.event_source == GDT_ES_SYNC) 27889580Smsmith p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.sync); 27989580Smsmith else 28089580Smsmith p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.async); 28189580Smsmith gdt_store_event(p->dvr.event_source, p->dvr.event_idx, 28289580Smsmith &p->dvr.event_data); 28389580Smsmith } else if (p->erase == 0xfe) { 28489580Smsmith gdt_clear_events(); 28589580Smsmith } else if (p->erase == 0) { 28689580Smsmith p->handle = gdt_read_event(p->handle, &p->dvr); 28789580Smsmith } else { 28889580Smsmith gdt_readapp_event((u_int8_t)p->erase, &p->dvr); 28989580Smsmith } 29089580Smsmith break; 29189580Smsmith } 29289580Smsmith 29389580Smsmith case GDT_IOCTL_STATIST: 29489580Smsmith { 29589580Smsmith gdt_statist_t *p; 29689580Smsmith 29789580Smsmith p = (gdt_statist_t *)cmdarg; 29889580Smsmith bcopy(&gdt_stat, p, sizeof(gdt_statist_t)); 29989580Smsmith break; 30089580Smsmith } 30189580Smsmith 30289580Smsmith default: 30389580Smsmith break; 30489580Smsmith } 30589580Smsmith 30689580Smsmith --gdt_stat.io_count_act; 30789580Smsmith return (0); 30889580Smsmith} 309