Date: Tue, 15 Jun 1999 09:48:40 +0800 From: Stephen Hocking-Senior Programmer PGS Tensor Perth <shocking@prth.pgs.com> To: current@freebsd.org, multimedia@freebsd.org Subject: Voodoo device driver for current enclosed (2nd try!) Message-ID: <199906150148.JAA09202@ariadne.tensor.pgs.com>
next in thread | raw e-mail | index | archive | help
Find herein the files that make up my so far unsuccessful attempt to write a
voodoo device driver. It was translated wholesale from Daryl Strauss's
driver for Linux, although I've messed up something along the way. At the
moment, it will lock up the machine hard shortly after mmaping the card's
memory. I'm about to go on holidays for a week, so I thought I'd throw this
out for you all to take a look at and hopefully find out what I've done
wrong.
In order to use it you will have to add to /sys/i386/conf/files.i386 the
following line -
pci/voodoo.c optional voodoo device-driver
And then to your machine config file
device voodoo0 # I hope this works....
You'll have to cut'n'paste the files into the appropriate directories (last
time I sent a uuencoded tar file, but that hasn't appeared yet), config your
kernel and recompile & reinstall your linux emulator module. You will also have
to have the appropriate version of glide for your card (note that the driver
doesn't as yet support the voodoo3 series, although this would be trivial to
add), and a copy of the glide SDK. I've been using the little test programs
that come with the SDK. I apologise for the humungous size of this meesage, but I have nowhere I can put it up for public ftp.
------- CUT HERE --- /sys/pci/voodoo.c ----------
/*
* Copyright ME
*
* voodoo driver
* $Id: make_device_driver.sh,v 1.0 Tue Aug 18 14:09:07 EST 1998 crb Exp $"
*/
#include "pci.h"
#if NPCI >0
#include "opt_devfs.h"
#include "voodoo.h" /* generated file..
* defines NVOODOO */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h> /* SYSINIT stuff */
#include <sys/conf.h> /* cdevsw stuff */
#include <sys/kernel.h>
#include <sys/signalvar.h>
#include <sys/malloc.h> /* malloc region
* definitions */
#include <machine/clock.h> /* DELAY() */
#include <sys/mman.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <pci.h> /* NCPI definitions */
#include <pci/pcivar.h> /* pci variables etc. */
#include <pci/pcireg.h> /* pci register
* definitions etc. */
#include <sys/voodooio.h> /* voodoo IOCTL
* definitions */
#ifdef DEVFS
#include <sys/devfsext.h> /* DEVFS defintitions */
#endif /* DEVFS */
#ifndef _IOC_DIR
#define _IOC_DIR(x) (x & IOC_DIRMASK)
#endif
#define VENDOR_3DFX 0x121a
#define VENDOR_ALLIANCE 0x1142
#define ID_VOODOO1 1
#define ID_VOODOO2 2
#define ID_AT3D 0x643d
#define VOODOO1 ((ID_VOODOO1 << 16) | VENDOR_3DFX)
#define VOODOO2 ((ID_VOODOO2 << 16) | VENDOR_3DFX)
#define RUSH ((ID_AT3D << 16) | VENDOR_ALLIANCE)
#define PCI_VENDOR_ID_FREEBSD 0x0
#define PCI_DEVICE_ID_FREEBSD 0x2
#define PCI_COMMAND_FREEBSD 0x4
#define PCI_REVISION_ID_FREEBSD 0x8
#define PCI_BASE_ADDRESS_0_FREEBSD 0x10
#define SST1_PCI_SPECIAL1_FREEBSD 0x40
#define SST1_PCI_SPECIAL2_FREEBSD 0x44
#define SST1_PCI_SPECIAL3_FREEBSD 0x48
#define SST1_PCI_SPECIAL4_FREEBSD 0x54
#define VGA_INPUT_STATUS_1C 0x3DA
#define VGA_MISC_OUTPUT_READ 0x3cc
#define VGA_MISC_OUTPUT_WRITE 0x3c2
#define SC_INDEX 0x3c4
#define SC_DATA 0x3c5
/* Function prototypes (these should all be static except for voodoointr()) */
static d_open_t voodooopen;
static d_close_t voodooclose;
static d_ioctl_t voodooioctl;
static d_mmap_t voodoommap;
static char *voodooprobe(pcici_t tag, pcidi_t type);
static void voodooattach(pcici_t tag, int unit);
static u_long voodoocount;
typedef struct pioData_t {
short port;
short size;
int device;
void *value;
} pioData;
typedef struct cardInfo_t {
pcici_t tag;
vm_offset_t virbase, physbase;
int vendor;
pcidi_t type;
int addr;
struct file *curFile;
} cardInfo;
#define MAXCARDS 16
cardInfo cards[MAXCARDS];
static int numCards=0;
#define CDEV_MAJOR 107
static struct cdevsw voodoo_cdevsw = {
voodooopen,
voodooclose,
noread,
nowrite,
voodooioctl,
NULL,
noreset,
nodevtotty,
nopoll,
voodoommap,
nostrategy,
"voodoo",
noparms,
CDEV_MAJOR,
nodump,
nopsize,
0,
0,
-1
};
static struct pci_device voodoo_device = {
"voodoo",
voodooprobe,
voodooattach,
&voodoocount,
NULL
};
/* The DATA_SET macro includes the pci device in the set of pci devices
* that will be probed at config time.
*/
#ifdef COMPAT_PCI_DRIVER
COMPAT_PCI_DRIVER (voodoo, voodoo_device);
#else
DATA_SET(pcidevice_set, voodoo_device);
#endif
#define UNIT(dev) minor(dev) /* assume one minor
* number per unit */
/*
* One of these per allocated device
*/
struct voodoo_softc
{
#ifdef DEVFS
static void *devfs_token;
#endif
};
typedef struct voodoo_softc *sc_p;
static sc_p sca[NVOODOO];
/* this function should discriminate if this device is
* or is not handled by this driver, often this will be
* as simple as testing the pci id of the device
*/
static void storeCard(pcici_t tag, pcidi_t type, char *name)
{
cards[numCards].tag = tag;
cards[numCards].type = (type & 0xffff0000) >> 16;
cards[numCards].vendor = type & 0xffff;
pci_map_mem(tag, PCI_MAP_REG_START, & cards[numCards].virbase, &cards[numCards].physbase);
cards[numCards].physbase &= ~0xF;
/* cards[numCards].physbase = (pci_cfgread(tag, PCIR_MAPS, 4) & ~0xF);*/
printf("%s has mem at phys 0x%lx, vir 0x%lx type 0x%x, vendor 0x%x\n",
name, cards[numCards].physbase, cards[numCards].virbase,
cards[numCards].type, cards[numCards].vendor);
/* Read configuration here */
numCards++;
}
static char *
voodooprobe(pcici_t tag, pcidi_t type)
{
char *board_type = (char *)0;
switch (type)
{
case VOODOO1:
board_type = "3DFX Voodoo 1";
storeCard(tag, type, board_type);
break;
case VOODOO2:
board_type = "3DFX Voodoo 2";
storeCard(tag, type, board_type);
break;
case RUSH:
board_type = "AT3D Rush";
storeCard(tag, type, board_type);
break;
};
return board_type;
}
/*
* Called if the probe succeeded.
*/
static void
voodooattach(pcici_t tag, int unit)
{
sc_p scp = sca[unit];
/* Allocate storage for this instance . */
scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
if (scp == NULL)
{
uprintf("voodoo%d failed to allocate driver storage\n", unit);
return;
}
bzero(scp, sizeof(*scp));
sca[unit] = scp;
/* Store whatever seems wise. */
#if DEVFS
scp->devfs_token = devfs_add_devswf(&voodoo_cdevsw, unit, DV_CHR,
UID_ROOT, GID_KMEM, 0600, "3dfx%d", unit);
#endif
/* Set up video mem addresses and port i/o addresses. */
}
/*
* Macro to check that the unit number is valid
* Often this isn't needed as once the open() is performed,
* the unit number is pretty much safe.. The exception would be if we
* implemented devices that could "go away". in which case all these routines
* would be wise to check the number, DIAGNOSTIC or not.
*/
#define CHECKUNIT(RETVAL) \
do { /* the do-while is a safe way to do this grouping */ \
if (unit > NVOODOO) { \
uprintf(__FUNCTION__ ":bad unit %d \n", unit); \
return (RETVAL); \
} \
if (scp == NULL) { \
uprintf( __FUNCTION__ ": unit %d not attached\n", unit); \
return (RETVAL); \
} \
} while (0)
#ifdef DIAGNOSTIC
#define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL)
#else /* DIAGNOSTIC */
#define CHECKUNIT_DIAG(RETVAL)
#endif /* DIAGNOSTIC */
static int doQueryBoards(void) {
/* printf("Called doQueryBoards %d\n", numCards); */
return numCards;
}
static int doQueryFetch(pioData *desc) {
char retchar;
short retword;
int retlong;
/* printf("Called doQueryFetch\n"); */
if (desc->device<0 || desc->device>=numCards) return EINVAL;
switch (desc->port) {
case PCI_VENDOR_ID_FREEBSD:
if (desc->size!=2) return EINVAL;
copyout(&cards[desc->device].vendor, desc->value, desc->size);
return 0;
case PCI_DEVICE_ID_FREEBSD:
if (desc->size!=2) return EINVAL;
copyout(&cards[desc->device].type, desc->value, desc->size);
return 0;
case PCI_BASE_ADDRESS_0_FREEBSD:
if (desc->size!=4) return EINVAL;
copyout(&cards[desc->device].addr, desc->value, desc->size);
return 0;
case SST1_PCI_SPECIAL1_FREEBSD:
if (desc->size!=4) return EINVAL;
break;
case PCI_REVISION_ID_FREEBSD:
if (desc->size!=1) return EINVAL;
break;
case SST1_PCI_SPECIAL4_FREEBSD:
if (desc->size!=4) return EINVAL;
break;
default:
return EINVAL;
}
switch (desc->size) {
case 1:
retchar = pci_cfgread(cards[desc->device].tag, desc->port, 1);
copyout(&retchar, desc->value, 1);
break;
case 2:
retword = pci_cfgread(cards[desc->device].tag, desc->port, 2);
copyout(&retword, desc->value, 2);
break;
case 4:
retlong = pci_cfgread(cards[desc->device].tag, desc->port, 4);
copyout(&retlong, desc->value, 4);
break;
default:
return EINVAL;
}
return 0;
}
static int doQueryUpdate(pioData *desc) {
int retval;
int preval;
int mask;
char retchar;
short retword;
int retlong;
printf("Called doQueryUpdate\n");
if (desc->device<0 || desc->device>=numCards) return EINVAL;
switch (desc->port) {
case PCI_COMMAND_FREEBSD:
if (desc->size!=2) return EINVAL;
break;
case SST1_PCI_SPECIAL1_FREEBSD:
if (desc->size!=4) return EINVAL;
break;
case SST1_PCI_SPECIAL2_FREEBSD:
if (desc->size!=4) return EINVAL;
break;
case SST1_PCI_SPECIAL3_FREEBSD:
if (desc->size!=4) return EINVAL;
break;
case SST1_PCI_SPECIAL4_FREEBSD:
if (desc->size!=4) return EINVAL;
break;
default:
return EINVAL;
}
retval = pci_cfgread(cards[desc->device].tag, desc->port & ~0x3, 4);
switch (desc->size) {
case 1:
copyin(desc->value, &retchar, 1);
preval=retchar<<(8*(desc->port&0x3));
mask=0xFF<<(8*(desc->port&0x3));
break;
case 2:
copyin(desc->value, &retword, 2);
preval=retword<<(8*(desc->port&0x3));
mask=0xFFFF<<(8*(desc->port&0x3));
break;
case 4:
copyin(desc->value, &retlong, 4);
preval=retlong;
mask=~0;
break;
default:
return EINVAL;
}
retval = (retval & ~mask) | preval;
printf("Updating port %d with 0x%x\n", desc->port, retval);
pci_cfgwrite(cards[desc->device].tag, desc->port, retval, 4);
return 0;
}
static int doQuery(unsigned int cmd, pioData *desc) {
/* printf("Called doQuery\n"); */
if (_IOC_NR(cmd)==2) return doQueryBoards();
if (_IOC_NR(cmd)==3) return doQueryFetch(desc);
if (_IOC_NR(cmd)==4) return doQueryUpdate(desc);
return EINVAL;
}
static int doPIORead(pioData *desc) {
char retchar;
short retword;
int retlong;
printf("called doPIORead\n");
switch (desc->port) {
case VGA_INPUT_STATUS_1C:
break;
case SC_INDEX:
break;
case SC_DATA:
break;
case VGA_MISC_OUTPUT_READ:
break;
default:
return EPERM;
}
if (desc->size!=1) {
return EINVAL;
}
switch (desc->size) {
case 1:
retchar=inb(desc->port);
copyout(&retchar, desc->value, sizeof(char));
break;
case 2:
retword=inw(desc->port);
copyout(&retword, desc->value, sizeof(short));
break;
case 4:
retlong=inl(desc->port);
copyout(&retlong, desc->value, sizeof(int));
break;
default:
return EINVAL;
}
return 0;
}
static int doPIOWrite(pioData *desc) {
char retchar;
short retword;
int retlong;
printf("Called doPIOWrite\n");
switch (desc->port) {
case SC_INDEX:
break;
case SC_DATA:
break;
case VGA_MISC_OUTPUT_WRITE:
break;
default:
return EPERM;
}
if (desc->size!=1) {
return EINVAL;
}
switch (desc->size) {
case 1:
copyin(desc->value, &retchar, sizeof(char));
outb(desc->port, retchar);
break;
case 2:
copyin(desc->value, &retword, sizeof(short));
outw(desc->port, retword);
break;
case 4:
copyin(desc->value, &retlong, sizeof(int));
outl(desc->port, retlong);
break;
default:
return EINVAL;
}
return 0;
}
static int doPIO(unsigned int cmd, pioData *desc) {
printf("Called doPIO\n");
if (_IOC_DIR(cmd)==IOCV_OUT) return doPIORead(desc);
if (_IOC_DIR(cmd)==IOCV_IN) return doPIOWrite(desc);
return EINVAL;
}
static int
voodooioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc * p)
{
int unit = UNIT(dev);
sc_p scp = sca[unit];
pioData *desc = data;
CHECKUNIT_DIAG(ENXIO);
/*
printf("Hey, somebody ioctl'd me with %x at %x!!\n", cmd, data);
if (data != NULL) printf("desc->device %d, desc->port %d, desc->size %d desc->value 0x%x\n",
desc->device, desc->port, desc->size, desc->value);
*/
switch (_IOC_TYPE(cmd))
{
case '3':
return doQuery(cmd, desc);
break;
case 0:
return doPIO(cmd, desc);
break;
default:
printf("And I didn't like it!\n");
return ENXIO;
}
return (0);
}
/*
* You also need read, write, open, close routines.
* This should get you started
*/
static int
voodooopen(dev_t dev, int oflags, int devtype, struct proc * p)
{
int unit = UNIT(dev);
sc_p scp = sca[unit];
printf("Voodoo opened!\n");
CHECKUNIT(ENXIO);
/* Do processing */
return (0);
}
static int
voodooclose(dev_t dev, int fflag, int devtype, struct proc * p)
{
int unit = UNIT(dev);
sc_p scp = sca[unit];
CHECKUNIT_DIAG(ENXIO);
/* Do processing */
return (0);
}
static int
voodoommap(dev_t dev, vm_offset_t offset, int nprot)
{
int unit = UNIT(dev), i;
sc_p scp = sca[unit];
CHECKUNIT_DIAG(-1);
printf("Someone trying to mmap me on unit %d..\n", unit);
/* Do processing */
if (offset >= 0x1000000)
return (-1);
return (i386_btop(cards[unit].physbase + offset));
}
/*
* Now for some driver initialization. There are basically 2 options
* here you can either use the drvinit function for initialization that
* needs to occur before any probing is done, or keep state in a global
* you can use in the probe routine to see if probe is being called for
* the fist time, and do your initalization there.
*/
static void
voodoo_drvinit(void *unused)
{
dev_t dev;
dev = makedev(CDEV_MAJOR, 0);
cdevsw_add(&voodoo_cdevsw);
}
SYSINIT(voodoodev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR,
voodoo_drvinit, NULL)
#endif /* NPCI */
------------ CUT HERE -------- /sys/sys/voodooio.h -------------
/*
* Definitions needed to access the voodoo device (ioctls etc)
* see mtio.h , ioctl.h as examples
*/
#ifndef SYS_DHIO_H
#define SYS_DHIO_H
#ifndef KERNEL
#include <sys/types.h>
#endif
/* #include <sys/ioccom.h> */
/*
* define an ioctl here
*/
#define DHIOCRESET _IO('D', 0) /* reset the voodoo device */
#define GETVOODOO 0x3302
#define SETVOODOO 0x3303
#define MOREVOODOO 0x3300
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
#define _IOC_SIZEBITS 14
#define _IOC_DIRBITS 2
#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
#define _IOC_NRSHIFT 0
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
/*
* Direction bits.
*/
#define _IOC_NONE 0U
#define _IOC_WRITE 1U
#define _IOC_READ 2U
#define _IOCV(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
/* used to create numbers */
#define _IOV(type,nr) _IOCV(_IOC_NONE,(type),(nr),0)
#define _IORV(type,nr,size) _IOCV(_IOC_READ,(type),(nr),sizeof(size))
#define _IOWV(type,nr,size) _IOCV(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWRV(type,nr,size) _IOCV(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
/* used to decode ioctl numbers.. */
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
/* ...and for the drivers/sound files... */
#define IOCV_IN (_IOC_WRITE << _IOC_DIRSHIFT)
#define IOCV_OUT (_IOC_READ << _IOC_DIRSHIFT)
#define IOCV_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
#endif
----------------- CUT HERE ---------- /sys/i386/linux/linux_ioctl.c --------
/*
* Copyright (c) 1994-1995 Søren Schmidt
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: linux_ioctl.c,v 1.33 1999/05/09 16:04:04 peter Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/proc.h>
#include <sys/cdio.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/tty.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <sys/sockio.h>
#include <machine/soundcard.h>
#include <machine/console.h>
#include <i386/linux/linux.h>
#include <i386/linux/linux_proto.h>
#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
struct linux_termio {
unsigned short c_iflag;
unsigned short c_oflag;
unsigned short c_cflag;
unsigned short c_lflag;
unsigned char c_line;
unsigned char c_cc[LINUX_NCC];
};
struct linux_termios {
unsigned long c_iflag;
unsigned long c_oflag;
unsigned long c_cflag;
unsigned long c_lflag;
unsigned char c_line;
unsigned char c_cc[LINUX_NCCS];
};
struct linux_winsize {
unsigned short ws_row, ws_col;
unsigned short ws_xpixel, ws_ypixel;
};
static struct speedtab sptab[] = {
{ 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 },
{ 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 },
{ 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 },
{ 2400, 11 }, { 4800, 12 }, { 9600, 13 },
{ 19200, 14 }, { 38400, 15 },
{ 57600, 4097 }, { 115200, 4098 }, {-1, -1 }
};
struct linux_serial_struct {
int type;
int line;
int port;
int irq;
int flags;
int xmit_fifo_size;
int custom_divisor;
int baud_base;
unsigned short close_delay;
char reserved_char[2];
int hub6;
unsigned short closing_wait;
unsigned short closing_wait2;
int reserved[4];
};
static int
linux_to_bsd_speed(int code, struct speedtab *table)
{
for ( ; table->sp_code != -1; table++)
if (table->sp_code == code)
return (table->sp_speed);
return -1;
}
static int
bsd_to_linux_speed(int speed, struct speedtab *table)
{
for ( ; table->sp_speed != -1; table++)
if (table->sp_speed == speed)
return (table->sp_code);
return -1;
}
static void
bsd_to_linux_termios(struct termios *bsd_termios,
struct linux_termios *linux_termios)
{
int i;
#ifdef DEBUG
printf("LINUX: BSD termios structure (input):\n");
printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
bsd_termios->c_iflag, bsd_termios->c_oflag,
bsd_termios->c_cflag, bsd_termios->c_lflag,
bsd_termios->c_ispeed, bsd_termios->c_ospeed);
printf("c_cc ");
for (i=0; i<NCCS; i++)
printf("%02x ", bsd_termios->c_cc[i]);
printf("\n");
#endif
linux_termios->c_iflag = 0;
if (bsd_termios->c_iflag & IGNBRK)
linux_termios->c_iflag |= LINUX_IGNBRK;
if (bsd_termios->c_iflag & BRKINT)
linux_termios->c_iflag |= LINUX_BRKINT;
if (bsd_termios->c_iflag & IGNPAR)
linux_termios->c_iflag |= LINUX_IGNPAR;
if (bsd_termios->c_iflag & PARMRK)
linux_termios->c_iflag |= LINUX_PARMRK;
if (bsd_termios->c_iflag & INPCK)
linux_termios->c_iflag |= LINUX_INPCK;
if (bsd_termios->c_iflag & ISTRIP)
linux_termios->c_iflag |= LINUX_ISTRIP;
if (bsd_termios->c_iflag & INLCR)
linux_termios->c_iflag |= LINUX_INLCR;
if (bsd_termios->c_iflag & IGNCR)
linux_termios->c_iflag |= LINUX_IGNCR;
if (bsd_termios->c_iflag & ICRNL)
linux_termios->c_iflag |= LINUX_ICRNL;
if (bsd_termios->c_iflag & IXON)
linux_termios->c_iflag |= LINUX_IXANY;
if (bsd_termios->c_iflag & IXON)
linux_termios->c_iflag |= LINUX_IXON;
if (bsd_termios->c_iflag & IXOFF)
linux_termios->c_iflag |= LINUX_IXOFF;
if (bsd_termios->c_iflag & IMAXBEL)
linux_termios->c_iflag |= LINUX_IMAXBEL;
linux_termios->c_oflag = 0;
if (bsd_termios->c_oflag & OPOST)
linux_termios->c_oflag |= LINUX_OPOST;
if (bsd_termios->c_oflag & ONLCR)
linux_termios->c_oflag |= LINUX_ONLCR;
if (bsd_termios->c_oflag & OXTABS)
linux_termios->c_oflag |= LINUX_XTABS;
linux_termios->c_cflag =
bsd_to_linux_speed(bsd_termios->c_ispeed, sptab);
linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4;
if (bsd_termios->c_cflag & CSTOPB)
linux_termios->c_cflag |= LINUX_CSTOPB;
if (bsd_termios->c_cflag & CREAD)
linux_termios->c_cflag |= LINUX_CREAD;
if (bsd_termios->c_cflag & PARENB)
linux_termios->c_cflag |= LINUX_PARENB;
if (bsd_termios->c_cflag & PARODD)
linux_termios->c_cflag |= LINUX_PARODD;
if (bsd_termios->c_cflag & HUPCL)
linux_termios->c_cflag |= LINUX_HUPCL;
if (bsd_termios->c_cflag & CLOCAL)
linux_termios->c_cflag |= LINUX_CLOCAL;
if (bsd_termios->c_cflag & CRTSCTS)
linux_termios->c_cflag |= LINUX_CRTSCTS;
linux_termios->c_lflag = 0;
if (bsd_termios->c_lflag & ISIG)
linux_termios->c_lflag |= LINUX_ISIG;
if (bsd_termios->c_lflag & ICANON)
linux_termios->c_lflag |= LINUX_ICANON;
if (bsd_termios->c_lflag & ECHO)
linux_termios->c_lflag |= LINUX_ECHO;
if (bsd_termios->c_lflag & ECHOE)
linux_termios->c_lflag |= LINUX_ECHOE;
if (bsd_termios->c_lflag & ECHOK)
linux_termios->c_lflag |= LINUX_ECHOK;
if (bsd_termios->c_lflag & ECHONL)
linux_termios->c_lflag |= LINUX_ECHONL;
if (bsd_termios->c_lflag & NOFLSH)
linux_termios->c_lflag |= LINUX_NOFLSH;
if (bsd_termios->c_lflag & TOSTOP)
linux_termios->c_lflag |= LINUX_TOSTOP;
if (bsd_termios->c_lflag & ECHOCTL)
linux_termios->c_lflag |= LINUX_ECHOCTL;
if (bsd_termios->c_lflag & ECHOPRT)
linux_termios->c_lflag |= LINUX_ECHOPRT;
if (bsd_termios->c_lflag & ECHOKE)
linux_termios->c_lflag |= LINUX_ECHOKE;
if (bsd_termios->c_lflag & FLUSHO)
linux_termios->c_lflag |= LINUX_FLUSHO;
if (bsd_termios->c_lflag & PENDIN)
linux_termios->c_lflag |= LINUX_PENDIN;
if (bsd_termios->c_lflag & IEXTEN)
linux_termios->c_lflag |= LINUX_IEXTEN;
for (i=0; i<LINUX_NCCS; i++)
linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE;
linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR];
linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT];
linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE];
linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL];
linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF];
linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL];
linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN];
linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME];
linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2];
linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE;
linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP];
linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART];
linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP];
linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT];
linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD];
linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE];
linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT];
for (i=0; i<LINUX_NCCS; i++) {
if (linux_termios->c_cc[i] == _POSIX_VDISABLE)
linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE;
}
linux_termios->c_line = 0;
#ifdef DEBUG
printf("LINUX: LINUX termios structure (output):\n");
printf("i=%08lx o=%08lx c=%08lx l=%08lx line=%d\n",
linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag,
linux_termios->c_lflag, linux_termios->c_line);
printf("c_cc ");
for (i=0; i<LINUX_NCCS; i++)
printf("%02x ", linux_termios->c_cc[i]);
printf("\n");
#endif
}
static void
linux_to_bsd_termios(struct linux_termios *linux_termios,
struct termios *bsd_termios)
{
int i;
#ifdef DEBUG
printf("LINUX: LINUX termios structure (input):\n");
printf("i=%08lx o=%08lx c=%08lx l=%08lx line=%d\n",
linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag,
linux_termios->c_lflag, linux_termios->c_line);
printf("c_cc ");
for (i=0; i<LINUX_NCCS; i++)
printf("%02x ", linux_termios->c_cc[i]);
printf("\n");
#endif
bsd_termios->c_iflag = 0;
if (linux_termios->c_iflag & LINUX_IGNBRK)
bsd_termios->c_iflag |= IGNBRK;
if (linux_termios->c_iflag & LINUX_BRKINT)
bsd_termios->c_iflag |= BRKINT;
if (linux_termios->c_iflag & LINUX_IGNPAR)
bsd_termios->c_iflag |= IGNPAR;
if (linux_termios->c_iflag & LINUX_PARMRK)
bsd_termios->c_iflag |= PARMRK;
if (linux_termios->c_iflag & LINUX_INPCK)
bsd_termios->c_iflag |= INPCK;
if (linux_termios->c_iflag & LINUX_ISTRIP)
bsd_termios->c_iflag |= ISTRIP;
if (linux_termios->c_iflag & LINUX_INLCR)
bsd_termios->c_iflag |= INLCR;
if (linux_termios->c_iflag & LINUX_IGNCR)
bsd_termios->c_iflag |= IGNCR;
if (linux_termios->c_iflag & LINUX_ICRNL)
bsd_termios->c_iflag |= ICRNL;
if (linux_termios->c_iflag & LINUX_IXON)
bsd_termios->c_iflag |= IXANY;
if (linux_termios->c_iflag & LINUX_IXON)
bsd_termios->c_iflag |= IXON;
if (linux_termios->c_iflag & LINUX_IXOFF)
bsd_termios->c_iflag |= IXOFF;
if (linux_termios->c_iflag & LINUX_IMAXBEL)
bsd_termios->c_iflag |= IMAXBEL;
bsd_termios->c_oflag = 0;
if (linux_termios->c_oflag & LINUX_OPOST)
bsd_termios->c_oflag |= OPOST;
if (linux_termios->c_oflag & LINUX_ONLCR)
bsd_termios->c_oflag |= ONLCR;
if (linux_termios->c_oflag & LINUX_XTABS)
bsd_termios->c_oflag |= OXTABS;
bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4;
if (linux_termios->c_cflag & LINUX_CSTOPB)
bsd_termios->c_cflag |= CSTOPB;
if (linux_termios->c_cflag & LINUX_PARENB)
bsd_termios->c_cflag |= PARENB;
if (linux_termios->c_cflag & LINUX_PARODD)
bsd_termios->c_cflag |= PARODD;
if (linux_termios->c_cflag & LINUX_HUPCL)
bsd_termios->c_cflag |= HUPCL;
if (linux_termios->c_cflag & LINUX_CLOCAL)
bsd_termios->c_cflag |= CLOCAL;
if (linux_termios->c_cflag & LINUX_CRTSCTS)
bsd_termios->c_cflag |= CRTSCTS;
bsd_termios->c_lflag = 0;
if (linux_termios->c_lflag & LINUX_ISIG)
bsd_termios->c_lflag |= ISIG;
if (linux_termios->c_lflag & LINUX_ICANON)
bsd_termios->c_lflag |= ICANON;
if (linux_termios->c_lflag & LINUX_ECHO)
bsd_termios->c_lflag |= ECHO;
if (linux_termios->c_lflag & LINUX_ECHOE)
bsd_termios->c_lflag |= ECHOE;
if (linux_termios->c_lflag & LINUX_ECHOK)
bsd_termios->c_lflag |= ECHOK;
if (linux_termios->c_lflag & LINUX_ECHONL)
bsd_termios->c_lflag |= ECHONL;
if (linux_termios->c_lflag & LINUX_NOFLSH)
bsd_termios->c_lflag |= NOFLSH;
if (linux_termios->c_lflag & LINUX_TOSTOP)
bsd_termios->c_lflag |= TOSTOP;
if (linux_termios->c_lflag & LINUX_ECHOCTL)
bsd_termios->c_lflag |= ECHOCTL;
if (linux_termios->c_lflag & LINUX_ECHOPRT)
bsd_termios->c_lflag |= ECHOPRT;
if (linux_termios->c_lflag & LINUX_ECHOKE)
bsd_termios->c_lflag |= ECHOKE;
if (linux_termios->c_lflag & LINUX_FLUSHO)
bsd_termios->c_lflag |= FLUSHO;
if (linux_termios->c_lflag & LINUX_PENDIN)
bsd_termios->c_lflag |= PENDIN;
if (linux_termios->c_lflag & IEXTEN)
bsd_termios->c_lflag |= IEXTEN;
for (i=0; i<NCCS; i++)
bsd_termios->c_cc[i] = _POSIX_VDISABLE;
bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR];
bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT];
bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE];
bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL];
bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF];
bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL];
bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN];
bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME];
bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2];
bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP];
bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART];
bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP];
bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT];
bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD];
bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE];
bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT];
for (i=0; i<NCCS; i++) {
if (bsd_termios->c_cc[i] == LINUX_POSIX_VDISABLE)
bsd_termios->c_cc[i] = _POSIX_VDISABLE;
}
bsd_termios->c_ispeed = bsd_termios->c_ospeed =
linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab);
#ifdef DEBUG
printf("LINUX: BSD termios structure (output):\n");
printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
bsd_termios->c_iflag, bsd_termios->c_oflag,
bsd_termios->c_cflag, bsd_termios->c_lflag,
bsd_termios->c_ispeed, bsd_termios->c_ospeed);
printf("c_cc ");
for (i=0; i<NCCS; i++)
printf("%02x ", bsd_termios->c_cc[i]);
printf("\n");
#endif
}
static void
bsd_to_linux_termio(struct termios *bsd_termios,
struct linux_termio *linux_termio)
{
struct linux_termios tmios;
bsd_to_linux_termios(bsd_termios, &tmios);
linux_termio->c_iflag = tmios.c_iflag;
linux_termio->c_oflag = tmios.c_oflag;
linux_termio->c_cflag = tmios.c_cflag;
linux_termio->c_lflag = tmios.c_lflag;
linux_termio->c_line = tmios.c_line;
memcpy(linux_termio->c_cc, tmios.c_cc, LINUX_NCC);
}
static void
linux_to_bsd_termio(struct linux_termio *linux_termio,
struct termios *bsd_termios)
{
struct linux_termios tmios;
int i;
tmios.c_iflag = linux_termio->c_iflag;
tmios.c_oflag = linux_termio->c_oflag;
tmios.c_cflag = linux_termio->c_cflag;
tmios.c_lflag = linux_termio->c_lflag;
for (i=0; i<LINUX_NCCS; i++)
tmios.c_cc[i] = LINUX_POSIX_VDISABLE;
memcpy(tmios.c_cc, linux_termio->c_cc, LINUX_NCC);
linux_to_bsd_termios(&tmios, bsd_termios);
}
static void
linux_tiocgserial(struct file *fp, struct linux_serial_struct *lss)
{
if (!fp || !lss)
return;
lss->type = LINUX_PORT_16550A;
lss->flags = 0;
lss->close_delay = 0;
}
static void
linux_tiocsserial(struct file *fp, struct linux_serial_struct *lss)
{
if (!fp || !lss)
return;
}
struct linux_cdrom_msf
{
u_char cdmsf_min0;
u_char cdmsf_sec0;
u_char cdmsf_frame0;
u_char cdmsf_min1;
u_char cdmsf_sec1;
u_char cdmsf_frame1;
};
struct linux_cdrom_tochdr
{
u_char cdth_trk0;
u_char cdth_trk1;
};
union linux_cdrom_addr
{
struct {
u_char minute;
u_char second;
u_char frame;
} msf;
int lba;
};
struct linux_cdrom_tocentry
{
u_char cdte_track;
u_char cdte_adr:4;
u_char cdte_ctrl:4;
u_char cdte_format;
union linux_cdrom_addr cdte_addr;
u_char cdte_datamode;
};
#if 0
static void
linux_to_bsd_msf_lba(u_char address_format,
union linux_cdrom_addr *lp, union msf_lba *bp)
{
if (address_format == CD_LBA_FORMAT)
bp->lba = lp->lba;
else {
bp->msf.minute = lp->msf.minute;
bp->msf.second = lp->msf.second;
bp->msf.frame = lp->msf.frame;
}
}
#endif
static void
bsd_to_linux_msf_lba(u_char address_format,
union msf_lba *bp, union linux_cdrom_addr *lp)
{
if (address_format == CD_LBA_FORMAT)
lp->lba = bp->lba;
else {
lp->msf.minute = bp->msf.minute;
lp->msf.second = bp->msf.second;
lp->msf.frame = bp->msf.frame;
}
}
static unsigned dirbits[4] = { IOC_VOID, IOC_OUT, IOC_IN, IOC_INOUT };
#define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
int
linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
{
struct termios bsd_termios;
struct linux_termios linux_termios;
struct linux_termio linux_termio;
struct filedesc *fdp = p->p_fd;
struct file *fp;
int (*func)(struct file *fp, u_long com, caddr_t data, struct proc *p);
int bsd_line, linux_line;
int error;
#ifdef DEBUG
printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n",
(long)p->p_pid, args->fd, args->cmd);
#endif
if ((unsigned)args->fd >= fdp->fd_nfiles
|| (fp = fdp->fd_ofiles[args->fd]) == 0)
return EBADF;
if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) {
return EBADF;
}
func = fp->f_ops->fo_ioctl;
switch (args->cmd & 0xffff) {
case LINUX_TCGETA:
if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
return error;
bsd_to_linux_termio(&bsd_termios, &linux_termio);
return copyout((caddr_t)&linux_termio, (caddr_t)args->arg,
sizeof(linux_termio));
case LINUX_TCSETA:
linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios);
return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
case LINUX_TCSETAW:
linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios);
return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
case LINUX_TCSETAF:
linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios);
return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
case LINUX_TCGETS:
if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
return error;
bsd_to_linux_termios(&bsd_termios, &linux_termios);
return copyout((caddr_t)&linux_termios, (caddr_t)args->arg,
sizeof(linux_termios));
case LINUX_TCSETS:
linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
case LINUX_TCSETSW:
linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
case LINUX_TCSETSF:
linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
case LINUX_TIOCGPGRP:
args->cmd = TIOCGPGRP;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCSPGRP:
args->cmd = TIOCSPGRP;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCGWINSZ:
args->cmd = TIOCGWINSZ;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCSWINSZ:
args->cmd = TIOCSWINSZ;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_FIONREAD:
args->cmd = FIONREAD;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_FIONBIO:
args->cmd = FIONBIO;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_FIOASYNC:
args->cmd = FIOASYNC;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_FIONCLEX:
args->cmd = FIONCLEX;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_FIOCLEX:
args->cmd = FIOCLEX;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCEXCL:
args->cmd = TIOCEXCL;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCNXCL:
args->cmd = TIOCNXCL;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCCONS:
args->cmd = TIOCCONS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCNOTTY:
args->cmd = TIOCNOTTY;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCGIFCONF:
args->cmd = OSIOCGIFCONF;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCGIFFLAGS:
args->cmd = SIOCGIFFLAGS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCGIFADDR:
args->cmd = OSIOCGIFADDR;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCGIFDSTADDR:
args->cmd = OSIOCGIFDSTADDR;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCGIFBRDADDR:
args->cmd = OSIOCGIFBRDADDR;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCGIFNETMASK:
args->cmd = OSIOCGIFNETMASK;
return ioctl(p, (struct ioctl_args *)args);
/* get hardware address */
case LINUX_SIOCGIFHWADDR:
{
int ifn;
struct ifnet *ifp;
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
struct linux_ifreq *ifr = (struct linux_ifreq *)args->arg;
/*
* Note that we don't actually respect the name in the ifreq structure, as
* Linux interface names are all different
*/
for (ifn = 0; ifn < if_index; ifn++) {
ifp = ifnet_addrs[ifn]->ifa_ifp; /* pointer to interface */
if (ifp->if_type == IFT_ETHER) { /* looks good */
/* walk the address list */
for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) {
if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && /* we have an address structure */
(sdl->sdl_family == AF_LINK) && /* it's a link address */
(sdl->sdl_type == IFT_ETHER)) { /* for an ethernet link */
return(copyout(LLADDR(sdl), (caddr_t)&ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN));
}
}
}
}
return(ENOENT); /* ??? */
}
case LINUX_SIOCADDMULTI:
args->cmd = SIOCADDMULTI;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCDELMULTI:
args->cmd = SIOCDELMULTI;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_FIOSETOWN:
args->cmd = FIOSETOWN;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCSPGRP:
args->cmd = SIOCSPGRP;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_FIOGETOWN:
args->cmd = FIOGETOWN;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCGPGRP:
args->cmd = SIOCGPGRP;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SIOCATMARK:
args->cmd = SIOCATMARK;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCSETD:
switch (args->arg) {
case LINUX_N_TTY:
bsd_line = TTYDISC;
return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
case LINUX_N_SLIP:
bsd_line = SLIPDISC;
return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
case LINUX_N_PPP:
bsd_line = PPPDISC;
return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
default:
return EINVAL;
}
case LINUX_TIOCGETD:
bsd_line = TTYDISC;
error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
if (error)
return error;
switch (bsd_line) {
case TTYDISC:
linux_line = LINUX_N_TTY;
break;
case SLIPDISC:
linux_line = LINUX_N_SLIP;
break;
case PPPDISC:
linux_line = LINUX_N_PPP;
break;
default:
return EINVAL;
}
return copyout(&linux_line, (caddr_t)args->arg,
sizeof(int));
case LINUX_SNDCTL_SEQ_RESET:
args->cmd = SNDCTL_SEQ_RESET;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_SYNC:
args->cmd = SNDCTL_SEQ_SYNC;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SYNTH_INFO:
args->cmd = SNDCTL_SYNTH_INFO;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_CTRLRATE:
args->cmd = SNDCTL_SEQ_CTRLRATE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_GETINCOUNT:
args->cmd = SNDCTL_SEQ_GETINCOUNT;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_PERCMODE:
args->cmd = SNDCTL_SEQ_PERCMODE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_FM_LOAD_INSTR:
args->cmd = SNDCTL_FM_LOAD_INSTR;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_TESTMIDI:
args->cmd = SNDCTL_SEQ_TESTMIDI;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_RESETSAMPLES:
args->cmd = SNDCTL_SEQ_RESETSAMPLES;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_NRSYNTHS:
args->cmd = SNDCTL_SEQ_NRSYNTHS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_NRMIDIS:
args->cmd = SNDCTL_SEQ_NRMIDIS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_MIDI_INFO:
args->cmd = SNDCTL_MIDI_INFO;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SEQ_TRESHOLD:
args->cmd = SNDCTL_SEQ_TRESHOLD;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_SYNTH_MEMAVL:
args->cmd = SNDCTL_SYNTH_MEMAVL;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_GETOPTR :
args->cmd = SNDCTL_DSP_GETOPTR;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_GETIPTR :
args->cmd = SNDCTL_DSP_GETIPTR;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_SETTRIGGER:
args->cmd = SNDCTL_DSP_SETTRIGGER;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_GETCAPS:
args->cmd = SNDCTL_DSP_GETCAPS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_RESET:
args->cmd = SNDCTL_DSP_RESET;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_SYNC:
args->cmd = SNDCTL_DSP_SYNC;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_SPEED:
args->cmd = SNDCTL_DSP_SPEED;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_STEREO:
args->cmd = SNDCTL_DSP_STEREO;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_GETBLKSIZE:
/* LINUX_SNDCTL_DSP_SETBLKSIZE */
args->cmd = SNDCTL_DSP_GETBLKSIZE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_SETFMT:
args->cmd = SNDCTL_DSP_SETFMT;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_PCM_WRITE_CHANNELS:
args->cmd = SOUND_PCM_WRITE_CHANNELS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_PCM_WRITE_FILTER:
args->cmd = SOUND_PCM_WRITE_FILTER;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_POST:
args->cmd = SNDCTL_DSP_POST;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_SUBDIVIDE:
args->cmd = SNDCTL_DSP_SUBDIVIDE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_SETFRAGMENT:
args->cmd = SNDCTL_DSP_SETFRAGMENT;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_GETFMTS:
args->cmd = SNDCTL_DSP_GETFMTS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_GETOSPACE:
args->cmd = SNDCTL_DSP_GETOSPACE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_GETISPACE:
args->cmd = SNDCTL_DSP_GETISPACE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SNDCTL_DSP_NONBLOCK:
args->cmd = SNDCTL_DSP_NONBLOCK;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_VOLUME:
args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_BASS:
args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_TREBLE:
args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_SYNTH:
args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_PCM:
args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_SPEAKER:
args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_LINE:
args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_MIC:
args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_CD:
args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_IMIX:
args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_ALTPCM:
args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_RECLEV:
args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_IGAIN:
args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_OGAIN:
args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_LINE1:
args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_LINE2:
args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_WRITE_LINE3:
args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
return ioctl(p, (struct ioctl_args *)args);
case LINUX_SOUND_MIXER_READ_DEVMASK:
args->cmd = SOUND_MIXER_READ_DEVMASK;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_TIOCGSERIAL:
linux_tiocgserial(fp, (struct linux_serial_struct *)args->arg);
return 0;
case LINUX_TIOCSSERIAL:
linux_tiocsserial(fp, (struct linux_serial_struct *)args->arg);
return 0;
case LINUX_TCFLSH:
args->cmd = TIOCFLUSH;
switch (args->arg) {
case LINUX_TCIFLUSH:
args->arg = FREAD;
break;
case LINUX_TCOFLUSH:
args->arg = FWRITE;
break;
case LINUX_TCIOFLUSH:
args->arg = FREAD | FWRITE;
break;
default:
return EINVAL;
}
return ioctl(p, (struct ioctl_args *)args);
case LINUX_VT_OPENQRY:
args->cmd = VT_OPENQRY;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_VT_GETMODE:
args->cmd = VT_GETMODE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_VT_SETMODE:
{
struct vt_mode *mode;
args->cmd = VT_SETMODE;
mode = (struct vt_mode *)args->arg;
if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig))
mode->frsig = mode->acqsig;
return ioctl(p, (struct ioctl_args *)args);
}
case LINUX_VT_GETSTATE:
args->cmd = VT_GETACTIVE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_VT_ACTIVATE:
args->cmd = VT_ACTIVATE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_VT_WAITACTIVE:
args->cmd = VT_WAITACTIVE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_KDGKBMODE:
args->cmd = KDGKBMODE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_KDSKBMODE:
{
int kbdmode;
switch (args->arg) {
case LINUX_KBD_RAW:
kbdmode = K_RAW;
return (*func)(fp, KDSKBMODE, (caddr_t)&kbdmode, p);
case LINUX_KBD_XLATE:
kbdmode = K_XLATE;
return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p);
case LINUX_KBD_MEDIUMRAW:
kbdmode = K_RAW;
return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p);
default:
return EINVAL;
}
}
case LINUX_KDGETMODE:
args->cmd = KDGETMODE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_KDSETMODE:
args->cmd = KDSETMODE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_KDSETLED:
args->cmd = KDSETLED;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_KDGETLED:
args->cmd = KDGETLED;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_KIOCSOUND:
args->cmd = KIOCSOUND;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_KDMKTONE:
args->cmd = KDMKTONE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMPAUSE:
args->cmd = CDIOCPAUSE;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMRESUME:
args->cmd = CDIOCRESUME;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMPLAYMSF:
args->cmd = CDIOCPLAYMSF;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMPLAYTRKIND:
args->cmd = CDIOCPLAYTRACKS;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMSTART:
args->cmd = CDIOCSTART;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMSTOP:
args->cmd = CDIOCSTOP;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMEJECT:
args->cmd = CDIOCEJECT;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMRESET:
args->cmd = CDIOCRESET;
return ioctl(p, (struct ioctl_args *)args);
case LINUX_CDROMREADTOCHDR: {
struct ioc_toc_header th;
struct linux_cdrom_tochdr lth;
error = (*func)(fp, CDIOREADTOCHEADER, (caddr_t)&th, p);
if (!error) {
lth.cdth_trk0 = th.starting_track;
lth.cdth_trk1 = th.ending_track;
copyout((caddr_t)<h, (caddr_t)args->arg, sizeof(lth));
}
return error;
}
case LINUX_CDROMREADTOCENTRY: {
struct linux_cdrom_tocentry lte, *ltep =
(struct linux_cdrom_tocentry *)args->arg;
struct ioc_read_toc_single_entry irtse;
irtse.address_format = ltep->cdte_format;
irtse.track = ltep->cdte_track;
error = (*func)(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, p);
if (!error) {
lte = *ltep;
lte.cdte_ctrl = irtse.entry.control;
lte.cdte_adr = irtse.entry.addr_type;
bsd_to_linux_msf_lba(irtse.address_format,
&irtse.entry.addr, <e.cdte_addr);
copyout((caddr_t)<e, (caddr_t)args->arg, sizeof(lte));
}
return error;
}
case 0x3304:
case 0x3303:
case 0x3302: {
int myretval;
struct pioData {
short port;
short size;
int device;
void *value;
} *desc;
desc = (struct pioData *)args->arg;
myretval = (*func)(fp, args->cmd, (caddr_t)args->arg, p);
if (myretval != EINVAL) {
p->p_retval[0] = myretval;
return 0;
} else
return myretval;
}
}
uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n",
args->fd, (u_int)((args->cmd & 0xffff00) >> 8),
(int)((args->cmd & 0xffff00) >> 8), (u_int)(args->cmd & 0xff));
return EINVAL;
}
--
The views expressed above are not those of PGS Tensor.
"We've heard that a million monkeys at a million keyboards could produce
the Complete Works of Shakespeare; now, thanks to the Internet, we know
this is not true." Robert Wilensky, University of California
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-multimedia" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199906150148.JAA09202>
