iir_ctrl.c revision 119418
189580Smsmith/* 289580Smsmith * Copyright (c) 2000-01 Intel Corporation 389580Smsmith * All Rights Reserved 489580Smsmith * 589580Smsmith * Redistribution and use in source and binary forms, with or without 689580Smsmith * modification, are permitted provided that the following conditions 789580Smsmith * are met: 889580Smsmith * 1. Redistributions of source code must retain the above copyright 989580Smsmith * notice, this list of conditions, and the following disclaimer, 1089580Smsmith * without modification, immediately at the beginning of the file. 1189580Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1289580Smsmith * notice, this list of conditions and the following disclaimer in the 1389580Smsmith * documentation and/or other materials provided with the distribution. 1489580Smsmith * 3. The name of the author may not be used to endorse or promote products 1589580Smsmith * derived from this software without specific prior written permission. 1689580Smsmith * 1789580Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1889580Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1989580Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2089580Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2189580Smsmith * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2289580Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2389580Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2489580Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2589580Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2689580Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2789580Smsmith * SUCH DAMAGE. 2889580Smsmith */ 2989580Smsmith 3089580Smsmith/* 3189580Smsmith * iir_ctrl.c: Control functions and /dev entry points for /dev/iir* 3289580Smsmith * 3389580Smsmith * Written by: Achim Leubner <achim.leubner@intel.com> 3489580Smsmith * Fixes/Additions: Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com> 3589580Smsmith * 3689580Smsmith * TODO: 3789580Smsmith */ 3889580Smsmith 3989580Smsmith#ident "$Id: iir_ctrl.c 1.2 2001/07/18 11:17:22 achim Exp $" 40119418Sobrien#include <sys/cdefs.h> 41119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/iir/iir_ctrl.c 119418 2003-08-24 17:55:58Z obrien $"); 4289580Smsmith 4389580Smsmith#include <sys/param.h> 4489580Smsmith#include <sys/systm.h> 4595533Smike#include <sys/endian.h> 4689580Smsmith#include <sys/malloc.h> 4789580Smsmith#include <sys/kernel.h> 4889580Smsmith#include <sys/uio.h> 4989580Smsmith#include <sys/conf.h> 50114001Sscottl#include <sys/disk.h> 5189580Smsmith#include <sys/stat.h> 52114001Sscottl#include <sys/disklabel.h> 5389580Smsmith#include <machine/bus.h> 5489580Smsmith#include <vm/vm.h> 5589580Smsmith#include <vm/vm_kern.h> 5689580Smsmith#include <vm/vm_extern.h> 5789580Smsmith#include <vm/pmap.h> 5889580Smsmith 5989580Smsmith#include <dev/iir/iir.h> 6089580Smsmith 6189580Smsmith/* Entry points and other prototypes */ 6289580Smsmithstatic struct gdt_softc *gdt_minor2softc(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#define CDEV_MAJOR IIR_CDEV_MAJOR 7189580Smsmith 7289580Smsmith/* Normally, this is a static structure. But we need it in pci/iir_pci.c */ 7389580Smsmithstatic struct cdevsw iir_cdevsw = { 74111815Sphk .d_open = iir_open, 75111815Sphk .d_close = iir_close, 76111815Sphk .d_read = iir_read, 77111815Sphk .d_write = iir_write, 78111815Sphk .d_ioctl = iir_ioctl, 79111815Sphk .d_name = "iir", 80111815Sphk .d_maj = CDEV_MAJOR, 8189580Smsmith}; 8289580Smsmith 83114001Sscottl/* 84114001Sscottlstatic int iir_devsw_installed = 0; 85114001Sscottl*/ 8689580Smsmith#ifndef SDEV_PER_HBA 8789580Smsmithstatic int sdev_made = 0; 8889580Smsmith#endif 8989580Smsmithextern int gdt_cnt; 9089580Smsmithextern char ostype[]; 9189580Smsmithextern char osrelease[]; 9289580Smsmithextern gdt_statist_t gdt_stat; 9389580Smsmith 9489580Smsmith/* 9589580Smsmith * Given a controller number, 9689580Smsmith * make a special device and return the dev_t 9789580Smsmith */ 9889580Smsmithdev_t 9989580Smsmithgdt_make_dev(int unit) 10089580Smsmith{ 10189580Smsmith dev_t dev; 10289580Smsmith 10389580Smsmith#ifdef SDEV_PER_HBA 10489580Smsmith dev = make_dev(&iir_cdevsw, hba2minor(unit), UID_ROOT, GID_OPERATOR, 105114001Sscottl S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, "iir%d", unit); 10689580Smsmith#else 10789580Smsmith if (sdev_made) 10889580Smsmith return (0); 10989580Smsmith dev = make_dev(&iir_cdevsw, 0, UID_ROOT, GID_OPERATOR, 110114001Sscottl S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, "iir"); 11189580Smsmith sdev_made = 1; 11289580Smsmith#endif 11389580Smsmith return (dev); 11489580Smsmith} 11589580Smsmith 11689580Smsmithvoid 11789580Smsmithgdt_destroy_dev(dev_t dev) 11889580Smsmith{ 11989580Smsmith if (dev != NULL) 12089580Smsmith destroy_dev(dev); 12189580Smsmith} 12289580Smsmith 12389580Smsmith/* 12489580Smsmith * Given a minor device number, 12589580Smsmith * return the pointer to its softc structure 12689580Smsmith */ 12789580Smsmithstatic struct gdt_softc * 12889580Smsmithgdt_minor2softc(int minor_no) 12989580Smsmith{ 13089580Smsmith struct gdt_softc *gdt; 13189580Smsmith int hanum; 13289580Smsmith 13389580Smsmith#ifdef SDEV_PER_HBA 13489580Smsmith hanum = minor2hba(minor_no); 13589580Smsmith#else 13689580Smsmith hanum = minor_no; 13789580Smsmith#endif 13889580Smsmith 13989580Smsmith for (gdt = TAILQ_FIRST(&gdt_softcs); 14089580Smsmith gdt != NULL && gdt->sc_hanum != hanum; 14189580Smsmith gdt = TAILQ_NEXT(gdt, links)); 14289580Smsmith 14389580Smsmith return (gdt); 14489580Smsmith} 14589580Smsmith 14689580Smsmithstatic int 14789580Smsmithiir_open(dev_t dev, int flags, int fmt, d_thread_t * p) 14889580Smsmith{ 14989580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_open()\n")); 15089580Smsmith 15189580Smsmith#ifdef SDEV_PER_HBA 15289580Smsmith int minor_no; 15389580Smsmith struct gdt_softc *gdt; 15489580Smsmith 15589580Smsmith minor_no = minor(dev); 15689580Smsmith gdt = gdt_minor2softc(minor_no); 15789580Smsmith if (gdt == NULL) 15889580Smsmith return (ENXIO); 15989580Smsmith#endif 16089580Smsmith 16189580Smsmith return (0); 16289580Smsmith} 16389580Smsmith 16489580Smsmithstatic int 16589580Smsmithiir_close(dev_t dev, int flags, int fmt, d_thread_t * p) 16689580Smsmith{ 16789580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_close()\n")); 16889580Smsmith 16989580Smsmith#ifdef SDEV_PER_HBA 17089580Smsmith int minor_no; 17189580Smsmith struct gdt_softc *gdt; 17289580Smsmith 17389580Smsmith minor_no = minor(dev); 17489580Smsmith gdt = gdt_minor2softc(minor_no); 17589580Smsmith if (gdt == NULL) 17689580Smsmith return (ENXIO); 17789580Smsmith#endif 17889580Smsmith 17989580Smsmith return (0); 18089580Smsmith} 18189580Smsmith 18289580Smsmithstatic int 18389580Smsmithiir_write(dev_t dev, struct uio * uio, int ioflag) 18489580Smsmith{ 18589580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_write()\n")); 18689580Smsmith 18789580Smsmith#ifdef SDEV_PER_HBA 18889580Smsmith int minor_no; 18989580Smsmith struct gdt_softc *gdt; 19089580Smsmith 19189580Smsmith minor_no = minor(dev); 19289580Smsmith gdt = gdt_minor2softc(minor_no); 19389580Smsmith if (gdt == NULL) 19489580Smsmith return (ENXIO); 19589580Smsmith#endif 19689580Smsmith 19789580Smsmith return (0); 19889580Smsmith} 19989580Smsmith 20089580Smsmithstatic int 20189580Smsmithiir_read(dev_t dev, struct uio * uio, int ioflag) 20289580Smsmith{ 20389580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_read()\n")); 20489580Smsmith 20589580Smsmith#ifdef SDEV_PER_HBA 20689580Smsmith int minor_no; 20789580Smsmith struct gdt_softc *gdt; 20889580Smsmith 20989580Smsmith minor_no = minor(dev); 21089580Smsmith gdt = gdt_minor2softc(minor_no); 21189580Smsmith if (gdt == NULL) 21289580Smsmith return (ENXIO); 21389580Smsmith#endif 21489580Smsmith 21589580Smsmith return (0); 21689580Smsmith} 21789580Smsmith 21889580Smsmith/** 21989580Smsmith * This is the control syscall interface. 22089580Smsmith * It should be binary compatible with UnixWare, 22189580Smsmith * if not totally syntatically so. 22289580Smsmith */ 22389580Smsmith 22489580Smsmithstatic int 22589580Smsmithiir_ioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, d_thread_t * p) 22689580Smsmith{ 22789580Smsmith GDT_DPRINTF(GDT_D_DEBUG, ("iir_ioctl() cmd 0x%lx\n",cmd)); 22889580Smsmith 22989580Smsmith#ifdef SDEV_PER_HBA 23089580Smsmith int minor_no; 23189580Smsmith struct gdt_softc *gdt; 23289580Smsmith 23389580Smsmith minor_no = minor(dev); 23489580Smsmith gdt = gdt_minor2softc(minor_no); 23589580Smsmith if (gdt == NULL) 23689580Smsmith return (ENXIO); 23789580Smsmith#endif 23889580Smsmith ++gdt_stat.io_count_act; 23989580Smsmith if (gdt_stat.io_count_act > gdt_stat.io_count_max) 24089580Smsmith gdt_stat.io_count_max = gdt_stat.io_count_act; 24189580Smsmith 24289580Smsmith switch (cmd) { 24389580Smsmith case GDT_IOCTL_GENERAL: 24489580Smsmith { 24589580Smsmith gdt_ucmd_t *ucmd; 24689580Smsmith struct gdt_softc *gdt; 24789580Smsmith int lock; 24889580Smsmith 24989580Smsmith ucmd = (gdt_ucmd_t *)cmdarg; 25089580Smsmith gdt = gdt_minor2softc(ucmd->io_node); 25189580Smsmith if (gdt == NULL) 25289580Smsmith return (ENXIO); 25389580Smsmith lock = splcam(); 25489580Smsmith TAILQ_INSERT_TAIL(&gdt->sc_ucmd_queue, ucmd, links); 25589580Smsmith ucmd->complete_flag = FALSE; 25689580Smsmith splx(lock); 25789580Smsmith gdt_next(gdt); 25889580Smsmith if (!ucmd->complete_flag) 25989580Smsmith (void) tsleep((void *)ucmd, PCATCH | PRIBIO, "iirucw", 0); 26089580Smsmith break; 26189580Smsmith } 26289580Smsmith 26389580Smsmith case GDT_IOCTL_DRVERS: 26489580Smsmith *(int *)cmdarg = 26589580Smsmith (IIR_DRIVER_VERSION << 8) | IIR_DRIVER_SUBVERSION; 26689580Smsmith break; 26789580Smsmith 26889580Smsmith case GDT_IOCTL_CTRTYPE: 26989580Smsmith { 27089580Smsmith gdt_ctrt_t *p; 27189580Smsmith struct gdt_softc *gdt; 27289580Smsmith 27389580Smsmith p = (gdt_ctrt_t *)cmdarg; 27489580Smsmith gdt = gdt_minor2softc(p->io_node); 27589580Smsmith if (gdt == NULL) 27689580Smsmith return (ENXIO); 27789580Smsmith p->oem_id = 0x8000; 27889580Smsmith p->type = 0xfd; 27989580Smsmith p->info = (gdt->sc_bus << 8) | (gdt->sc_slot << 3); 28089580Smsmith p->ext_type = 0x6000 | gdt->sc_subdevice; 28189580Smsmith p->device_id = gdt->sc_device; 28289580Smsmith p->sub_device_id = gdt->sc_subdevice; 28389580Smsmith break; 28489580Smsmith } 28589580Smsmith 28689580Smsmith case GDT_IOCTL_OSVERS: 28789580Smsmith { 28889580Smsmith gdt_osv_t *p; 28989580Smsmith 29089580Smsmith p = (gdt_osv_t *)cmdarg; 29189580Smsmith p->oscode = 10; 29289580Smsmith p->version = osrelease[0] - '0'; 29389580Smsmith if (osrelease[1] == '.') 29489580Smsmith p->subversion = osrelease[2] - '0'; 29589580Smsmith else 29689580Smsmith p->subversion = 0; 29789580Smsmith if (osrelease[3] == '.') 29889580Smsmith p->revision = osrelease[4] - '0'; 29989580Smsmith else 30089580Smsmith p->revision = 0; 30189580Smsmith strcpy(p->name, ostype); 30289580Smsmith break; 30389580Smsmith } 30489580Smsmith 30589580Smsmith case GDT_IOCTL_CTRCNT: 30689580Smsmith *(int *)cmdarg = gdt_cnt; 30789580Smsmith break; 30889580Smsmith 30989580Smsmith case GDT_IOCTL_EVENT: 31089580Smsmith { 31189580Smsmith gdt_event_t *p; 31289580Smsmith int lock; 31389580Smsmith 31489580Smsmith p = (gdt_event_t *)cmdarg; 31589580Smsmith if (p->erase == 0xff) { 31689580Smsmith if (p->dvr.event_source == GDT_ES_TEST) 31789580Smsmith p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.test); 31889580Smsmith else if (p->dvr.event_source == GDT_ES_DRIVER) 31989580Smsmith p->dvr.event_data.size= sizeof(p->dvr.event_data.eu.driver); 32089580Smsmith else if (p->dvr.event_source == GDT_ES_SYNC) 32189580Smsmith p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.sync); 32289580Smsmith else 32389580Smsmith p->dvr.event_data.size = sizeof(p->dvr.event_data.eu.async); 32489580Smsmith lock = splcam(); 32589580Smsmith gdt_store_event(p->dvr.event_source, p->dvr.event_idx, 32689580Smsmith &p->dvr.event_data); 32789580Smsmith splx(lock); 32889580Smsmith } else if (p->erase == 0xfe) { 32989580Smsmith lock = splcam(); 33089580Smsmith gdt_clear_events(); 33189580Smsmith splx(lock); 33289580Smsmith } else if (p->erase == 0) { 33389580Smsmith p->handle = gdt_read_event(p->handle, &p->dvr); 33489580Smsmith } else { 33589580Smsmith gdt_readapp_event((u_int8_t)p->erase, &p->dvr); 33689580Smsmith } 33789580Smsmith break; 33889580Smsmith } 33989580Smsmith 34089580Smsmith case GDT_IOCTL_STATIST: 34189580Smsmith { 34289580Smsmith gdt_statist_t *p; 34389580Smsmith 34489580Smsmith p = (gdt_statist_t *)cmdarg; 34589580Smsmith bcopy(&gdt_stat, p, sizeof(gdt_statist_t)); 34689580Smsmith break; 34789580Smsmith } 34889580Smsmith 34989580Smsmith default: 35089580Smsmith break; 35189580Smsmith } 35289580Smsmith 35389580Smsmith --gdt_stat.io_count_act; 35489580Smsmith return (0); 35589580Smsmith} 356114001Sscottl 357114001Sscottl/* 358114001Sscottlstatic void 359114001Sscottliir_drvinit(void *unused) 360114001Sscottl{ 361114001Sscottl GDT_DPRINTF(GDT_D_DEBUG, ("iir_drvinit()\n")); 362114001Sscottl 363114001Sscottl if (!iir_devsw_installed) { 364114001Sscottl cdevsw_add(&iir_cdevsw); 365114001Sscottl iir_devsw_installed = 1; 366114001Sscottl } 367114001Sscottl} 368114001Sscottl 369114001SscottlSYSINIT(iir_dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, iir_drvinit, NULL) 370114001Sscottl*/ 371