/* $ZEL: sis1100_ioctl.c,v 1.5 2004/05/27 23:10:22 wuestner Exp $ */ /* * Copyright (c) 2001-2004 * Matthias Drochner, Peter Wuestner. 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. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. */ #include "sis1100_sc.h" #if !defined(__NetBSD__) && ! defined(__linux__) #error Invalid or Unknown Operating System #endif static int test_super(struct sis1100_softc* sc, struct sis1100_fdata* fd) { return 0; #ifdef __NetBSD__ if (suser(fd->p->p_ucred, &fd->p->p_acflag)) return EPERM; #elif __linux__ if (!capable(CAP_SYS_RAWIO)) return EPERM; #endif return 0; } #ifdef SIS1100_NEW_CTRL static int ioctl_ctrl_read(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_ctrl_reg* d) { if (fd->subdev==sis1100_subdev_ctrl) { SEM_LOCK(sc->sem_hw); d->val=plxreadlocal0(sc, d->offset&0x7ff); SEM_UNLOCK(sc->sem_hw); d->error=0; } else { if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; d->error=sis1100_remote_reg_read(sc, d->offset, &d->val, 1); } return 0; } static int ioctl_ctrl_write(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_ctrl_reg* d) { if (fd->subdev==sis1100_subdev_ctrl) { SEM_LOCK(sc->sem_hw); plxwritelocal0(sc, d->offset&0x7ff, d->val); SEM_UNLOCK(sc->sem_hw); d->error=0; } else { if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; d->error=sis1100_remote_reg_write(sc, d->offset, d->val, 0); } return 0; } #else static int ioctl_local_ctrl_read(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_ctrl_reg* d) { SEM_LOCK(sc->sem_hw); d->val=plxreadlocal0(sc, d->offset&0x7ff); SEM_UNLOCK(sc->sem_hw); d->error=0; return 0; } static int ioctl_local_ctrl_write(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_ctrl_reg* d) { SEM_LOCK(sc->sem_hw); plxwritelocal0(sc, d->offset&0x7ff, d->val); SEM_UNLOCK(sc->sem_hw); d->error=0; return 0; } static int ioctl_remote_ctrl_read(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_ctrl_reg* d) { if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; d->error=sis1100_remote_reg_read(sc, d->offset, &d->val, 0); return 0; } static int ioctl_remote_ctrl_write(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_ctrl_reg* d) { if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; d->error=sis1100_remote_reg_write(sc, d->offset, d->val, 0); return 0; } #endif static int ioctl_ident(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_ident* d) { d->local.hw_type=sc->local_ident&0xff; d->local.hw_version=(sc->local_ident>>8)&0xff; d->local.fw_type=(sc->local_ident>>16)&0xff; d->local.fw_version=(sc->local_ident>>24)&0xff; d->remote.hw_type=sc->remote_ident&0xff; d->remote.hw_version=(sc->remote_ident>>8)&0xff; d->remote.fw_type=(sc->remote_ident>>16)&0xff; d->remote.fw_version=(sc->remote_ident>>24)&0xff; d->remote_ok=sc->remote_hw!=sis1100_hw_invalid; d->remote_online=(sis1100readreg(sc, sr)&sr_synch)==sr_synch; return 0; } static int ioctl_remote_reset(struct sis1100_softc* sc, struct sis1100_fdata* fd) { #if 0 SEM_LOCK(sc->sem_hw); sis1100writereg(sc, cr, cr_rem_reset); switch (sc->remote_hw) { case sis1100_hw_invalid: SEM_UNLOCK(sc->sem_hw); return ENXIO; case sis1100_hw_pci: /* do nothing */ break; case sis1100_hw_vme: sis3100writeremreg(sc, vme_master_sc, 8, 1); break; case sis1100_hw_camac: break; } SEM_UNLOCK(sc->sem_hw); mdelay(500); sis1100_init_remote(sc); #endif return ENOTTY; } static int ioctl_devtype(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { *d=fd->subdev; return 0; } static int ioctl_driverversion(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { *d=SIS1100_Version; return 0; } static int ioctl_mindmalen(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { /* * 0: never use DMA * 1: always use DMA (if size>4) * >1: use DMA if transfersize (in Bytes) is >= mindmalen * -1: don't change old value */ int tmp[2]; tmp[0]=fd->mindmalen_r; tmp[1]=fd->mindmalen_w; if (d[0]>=0) fd->mindmalen_r=d[0]; if (d[1]>=0) fd->mindmalen_w=d[1]; d[0]=tmp[0]; d[1]=tmp[1]; return 0; } static int ioctl_setvmespace(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct vmespace* d) { if ((d->datasize!=1) && (d->datasize!=2) && (d->datasize!=4)) return EINVAL; fd->vmespace_am=d->am; fd->vmespace_datasize=d->datasize; if (d->swap>=0) { sc->user_wants_swap=d->swap; sis1100_update_swapping(sc, "ioctl_setvmespace"); } if (d->mindmalen>=0) { fd->mindmalen_r=d->mindmalen; fd->mindmalen_w=d->mindmalen; } return 0; } static int ioctl_swap(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { int old; old=sc->user_wants_swap; sc->user_wants_swap=*d; sis1100_update_swapping(sc, "ioctl_swap"); *d=old; return 0; } static int ioctl_3100_timeouts(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { /* * d[0]: bus error terms of 10**-9 s * d[1]: arbitration timeout in terms of 10**-3 s */ int tmp[2]; if ((fd->subdev!=sis1100_subdev_remote) || (sc->remote_hw!=sis1100_hw_vme)) return ENXIO; if (sis3100_get_timeouts(sc, tmp+0, tmp+1)) return EIO; if (sis3100_set_timeouts(sc, d[0], d[1])) return EIO; d[0]=tmp[0]; d[1]=tmp[1]; return 0; } static int ioctl_front_io(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { return sis1100_front_io(sc, d, 0); } static int ioctl_front_pulse(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { return sis1100_front_pulse(sc, d, 0); } static int ioctl_front_latch(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { return sis1100_front_latch(sc, d, 0); } static int ioctl_last_error(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { *d=fd->last_prot_err; return 0; } static int ioctl_mapsize(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { switch (fd->subdev) { case sis1100_subdev_remote: *d=sc->rem_size; break; case sis1100_subdev_ram: *d=sc->ram_size; break; case sis1100_subdev_ctrl: *d=sc->reg_size; break; case sis1100_subdev_dsp: *d=0; break; default: return EINVAL; } return 0; } static int ioctl_pipe(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_pipe* d) { int res; if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; res=sis1100_read_pipe(sc, d); return res; } static int ioctl_write_pipe(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_writepipe* d) { u_int32_t* list; int res; if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; #ifdef __NetBSD__ list=malloc(d->num*2*sizeof(u_int32_t), M_IOCTLOPS, M_WAITOK/*|M_CANFAIL*/); #elif __linux__ list=kmalloc(d->num*2*sizeof(u_int32_t), GFP_KERNEL); #endif if (!list) return ENOMEM; if ( #ifdef __NetBSD__ copyin(d->data, list, d->num*2*sizeof(u_int32_t)) #elif __linux__ copy_from_user(list, d->data, d->num*2*sizeof(u_int32_t)) #endif ) { res=EFAULT; goto raus; } res=0; d->error=sis1100_write_pipe(sc, d->am, 1/*space*/, d->num, list); raus: #ifdef __NetBSD__ free(list, M_IOCTLOPS); #elif __linux__ kfree(list); #endif return res; } static int ioctl_vme_probe(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { int dummy; if (sc->remote_hw!=sis1100_hw_vme) return ENXIO; if (sis1100_tmp_read(sc, *d, fd->vmespace_am, fd->vmespace_datasize, 1/*space*/, &dummy)) return EIO; return 0; } static int ioctl_vme_read(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_vme_req* d) { if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; d->error=sis1100_tmp_read(sc, d->addr, d->am, d->size, 1/*space*/, &d->data); return 0; } static int ioctl_vme_write(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_vme_req* d) { if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; d->error=sis1100_tmp_write(sc, d->addr, d->am, d->size, 1/*space*/, d->data); return 0; } static int ioctl_vme_block_read(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_vme_block_req* d) { int res; int space=1; #if 0 switch (sc->remote_hw) { case sis1100_hw_invalid: return ENXIO; case sis1100_hw_pci: space=1; break; case sis1100_hw_vme: space=1; break; case sis1100_hw_camac: space=1; break; case sis1100_hw_f1: space=1; break; case sis1100_hw_vertex: space=1; break; } #else if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; #endif res=sis1100_read_block(sc, fd, d->size, d->fifo, d->num, &d->num, space, d->am, d->addr, d->data, &d->error); return res; } static int ioctl_vme_super_block_read(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_vme_super_block_req* d) { struct sis1100_vme_block_req* reqs; int res, i; if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; #ifdef __NetBSD__ reqs=malloc(d->n*sizeof(struct sis1100_vme_block_req), M_IOCTLOPS, M_WAITOK/*|M_CANFAIL*/); #elif __linux__ reqs=kmalloc(d->n*sizeof(struct sis1100_vme_block_req), GFP_KERNEL); #endif if (!reqs) return ENOMEM; if ( #ifdef __NetBSD__ copyin(d->reqs, reqs, d->n*sizeof(struct sis1100_vme_block_req)) #elif __linux__ copy_from_user(reqs, d->reqs, d->n*sizeof(struct sis1100_vme_block_req)) #endif ) { res=EFAULT; goto raus; } d->error=0; for (i=0; in; i++) { struct sis1100_vme_block_req* r=reqs+i; res=sis1100_read_block(sc, fd, r->size, r->fifo, r->num, &r->num, 1/*space*/, r->am, r->addr, r->data, &r->error); if (res) { d->n=i; d->error=res; break; } } res=0; if ( #ifdef __NetBSD__ copyout(reqs, d->reqs, d->n*sizeof(struct sis1100_vme_block_req)) #elif __linux__ copy_to_user(d->reqs, reqs, d->n*sizeof(struct sis1100_vme_block_req)) #endif ) res=EFAULT; raus: #ifdef __NetBSD__ free(reqs, M_IOCTLOPS); #elif __linux__ kfree(reqs); #endif return res; } static int ioctl_vme_block_write(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_vme_block_req* d) { int res; if (sc->remote_hw==sis1100_hw_invalid) return ENXIO; res=sis1100_write_block(sc, fd, d->size, d->fifo, d->num, &d->num, 1/*space*/, d->am, d->addr, d->data, &d->error); return res; } static int ioctl_fifomode(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { int tmp; tmp=fd->fifo_mode; if (*d>=0) fd->fifo_mode=!!*d; *d=tmp; return 0; } static int ioctl_irq_ctl(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_irq_ctl* d) { return sis1100_irq_ctl(sc, fd, d); } static int ioctl_irq_get(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_irq_get* d) { return sis1100_irq_get(sc, fd, d); } static int ioctl_irq_ack(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_irq_ack* d) { return sis1100_irq_ack(sc, fd, d); } static int ioctl_irq_wait(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_irq_get* d) { return sis1100_irq_wait(sc, fd, d); } static int ioctl_dma_alloc(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_dma_alloc* d) { #ifdef __NetBSD__ return sis1100_dma_alloc(sc, fd, d); #elif __linux__ return ENOTTY; #endif } static int ioctl_dma_free(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_dma_alloc* d) { /*return sis1100_dma_free(sc, fd, d);*/ return ENOTTY; } #if 0 static int ioctl_reset(struct sis1100_softc* sc, struct sis1100_fdata* fd) { return sis1100_reset(sc); } #endif static int ioctl_cccz(struct sis1100_softc* sc, struct sis1100_fdata* fd) { u_int32_t data; int res; return 0; if (sc->remote_hw!=sis1100_hw_camac) return ENXIO; res=sis1100_tmp_camacread(sc, SIS5100_CAMACaddr(28, 8, 26), &data); pINFO(sc, "CCCZ: data=0x%x res=0x%x", data, res); return 0; } static int ioctl_cccc(struct sis1100_softc* sc, struct sis1100_fdata* fd) { u_int32_t data; int res; return 0; if (sc->remote_hw!=sis1100_hw_camac) return ENXIO; res=sis1100_tmp_camacread(sc, SIS5100_CAMACaddr(28, 9, 26), &data); pINFO(sc, "CCCC: data=0x%x res=0x%x", data, res); return 0; } static int ioctl_ccci(struct sis1100_softc* sc, struct sis1100_fdata* fd, int* d) { u_int32_t data; int res; if (sc->remote_hw!=sis1100_hw_camac) return ENXIO; res=sis5100writeremreg(sc, camac_sc, *d?1:0x1000, 0); /*res=sis1100_tmp_camacread(sc, SIS5100_CAMACaddr(30, 9, *d?26:24), &data);*/ pINFO(sc, "CCCI(%d): res=0x%x", *d, res); res=sis5100readremreg(sc, camac_sc, &data, 0); pINFO(sc, "CCCI : data=0x%x, res=0x%x", data, res); return 0; } static int ioctl_cnaf(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_camac_req* d) { u_int32_t addr; int res; addr=SIS5100_CAMACaddr(d->N, d->A, d->F); if ((d->F&0x18)==0x10) { /* write */ res=sis1100_tmp_camacwrite(sc, addr, d->data); d->data=(~res<<24)&0xc0000000; if ((res&~0x2c0)==0) { /* X or Q missing; not an error */ res=0; } } else { /* read or control */ res=sis1100_tmp_camacread(sc, addr, &d->data); d->data^=0xc0000000; } d->error=res; return 0; } static int ioctl_read_eeprom(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_eeprom_req* d) { return sis1100_read_eeprom(sc, d->num, d->addr, d->data); } static int ioctl_write_eeprom(struct sis1100_softc* sc, struct sis1100_fdata* fd, struct sis1100_eeprom_req* d) { if (test_super(sc, fd)) return EPERM; return sis1100_write_eeprom(sc, d->num, d->addr, d->data); } static int ioctl_jtag_enable(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { if (test_super(sc, fd)) return EPERM; *d<<=8; sis1100writereg(sc, jtag_csr.jtag_csrl, *d); return 0; } static int ioctl_jtag_ctrl(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { if (test_super(sc, fd)) return EPERM; sis1100writereg(sc, jtag_csr.jtag_csrb[1], *d); *d=sis1100readreg(sc, jtag_csr.jtag_csrl); return 0; } static int ioctl_jtag_data(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { *d=sis1100readreg(sc, jtag_data); return 0; } static int ioctl_jtag_put(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { if (test_super(sc, fd)) return EPERM; sis1100writereg(sc, jtag_csr.jtag_csrl, *d); return 0; } static int ioctl_jtag_get(struct sis1100_softc* sc, struct sis1100_fdata* fd, u_int32_t* d) { *d=sis1100readreg(sc, jtag_csr.jtag_csrl); return 0; } static int _sis1100_ioctl(struct sis1100_softc* sc, struct sis1100_fdata* fd, unsigned int cmd, void* data) { int res=0; switch (cmd) { case SIS1100_SETVMESPACE: res=ioctl_setvmespace(sc, fd, (struct vmespace*)data); break; case SIS3100_VME_PROBE: res=ioctl_vme_probe(sc, fd, (int*)data); break; case SIS3100_VME_READ: res=ioctl_vme_read(sc, fd, (struct sis1100_vme_req*)data); break; case SIS3100_VME_WRITE: res=ioctl_vme_write(sc, fd, (struct sis1100_vme_req*)data); break; case SIS3100_VME_BLOCK_READ: res=ioctl_vme_block_read(sc, fd, (struct sis1100_vme_block_req*)data); break; case SIS3100_VME_BLOCK_WRITE: res=ioctl_vme_block_write(sc, fd, (struct sis1100_vme_block_req*)data); break; #ifdef SIS1100_NEW_CTRL case SIS1100_CTRL_READ: res=ioctl_ctrl_read(sc, fd, (struct sis1100_ctrl_reg*)data); break; case SIS1100_CTRL_WRITE: res=ioctl_ctrl_write(sc, fd, (struct sis1100_ctrl_reg*)data); break; #else case SIS1100_LOCAL_CTRL_READ: res=ioctl_local_ctrl_read(sc, fd, (struct sis1100_ctrl_reg*)data); break; case SIS1100_LOCAL_CTRL_WRITE: res=ioctl_local_ctrl_write(sc, fd, (struct sis1100_ctrl_reg*)data); break; case SIS1100_REMOTE_CTRL_READ: res=ioctl_remote_ctrl_read(sc, fd, (struct sis1100_ctrl_reg*)data); break; case SIS1100_REMOTE_CTRL_WRITE: res=ioctl_remote_ctrl_write(sc, fd, (struct sis1100_ctrl_reg*)data); break; #endif case SIS1100_PIPE: res=ioctl_pipe(sc, fd, (struct sis1100_pipe*)data); break; case SIS1100_MAPSIZE: res=ioctl_mapsize(sc, fd, (u_int32_t*)data); break; case SIS1100_LAST_ERROR: res=ioctl_last_error(sc, fd, (u_int32_t*)data); break; case SIS1100_IDENT: res=ioctl_ident(sc, fd, (struct sis1100_ident*)data); break; case SIS1100_FIFOMODE: res=ioctl_fifomode(sc, fd, (int*)data); break; case SIS1100_IRQ_CTL: res=ioctl_irq_ctl(sc, fd, (struct sis1100_irq_ctl*)data); break; case SIS1100_IRQ_GET: res=ioctl_irq_get(sc, fd, (struct sis1100_irq_get*)data); break; case SIS1100_IRQ_ACK: res=ioctl_irq_ack(sc, fd, (struct sis1100_irq_ack*)data); break; case SIS1100_IRQ_WAIT: res=ioctl_irq_wait(sc, fd, (struct sis1100_irq_get*)data); break; case SIS1100_MINDMALEN: res=ioctl_mindmalen(sc, fd, (int*)data); break; case SIS1100_FRONT_IO: res=ioctl_front_io(sc, fd, (u_int32_t*)data); break; case SIS1100_FRONT_PULSE: res=ioctl_front_pulse(sc, fd, (u_int32_t*)data); break; case SIS1100_FRONT_LATCH: res=ioctl_front_latch(sc, fd, (u_int32_t*)data); break; case SIS3100_VME_SUPER_BLOCK_READ: res=ioctl_vme_super_block_read(sc, fd, (struct sis1100_vme_super_block_req*)data); break; case SIS1100_WRITE_PIPE: res=ioctl_write_pipe(sc, fd, (struct sis1100_writepipe*)data); break; case SIS1100_DMA_ALLOC: res=ioctl_dma_alloc(sc, fd, (struct sis1100_dma_alloc*)data); break; case SIS1100_DMA_FREE: res=ioctl_dma_free(sc, fd, (struct sis1100_dma_alloc*)data); break; case SIS5100_CCCZ: res=ioctl_cccz(sc, fd); break; case SIS5100_CCCC: res=ioctl_cccc(sc, fd); break; case SIS5100_CCCI: res=ioctl_ccci(sc, fd, (int*)data); break; case SIS5100_CNAF: res=ioctl_cnaf(sc, fd, (struct sis1100_camac_req*)data); break; case SIS1100_SWAP: res=ioctl_swap(sc, fd, (int*)data); break; case SIS3100_TIMEOUTS: res=ioctl_3100_timeouts(sc, fd, (int*)data); break; case SIS1100_DSP_LOAD: res=sis1100_dsp_load(sc, fd, (struct sis1100_dsp_code*)data); break; case SIS1100_DSP_RESET: res=sis1100_dsp_reset(sc, fd); break; case SIS1100_DSP_START: res=sis1100_dsp_start(sc, fd); break; #if 0 case SIS1100_RESET: res=ioctl_reset(sc, fd); break; #endif case SIS1100_REMOTE_RESET: res=ioctl_remote_reset(sc, fd); break; case SIS1100_DEVTYPE: res=ioctl_devtype(sc, fd, (int*)data); break; case SIS1100_DRIVERVERSION: res=ioctl_driverversion(sc, fd, (int*)data); break; case SIS1100_READ_EEPROM: res=ioctl_read_eeprom(sc, fd, (struct sis1100_eeprom_req*)data); break; case SIS1100_WRITE_EEPROM: res=ioctl_write_eeprom(sc, fd, (struct sis1100_eeprom_req*)data); break; case SIS1100_JTAG_ENABLE: res=ioctl_jtag_enable(sc, fd, (u_int32_t*)data); break; case SIS1100_JTAG_CTRL: res=ioctl_jtag_ctrl(sc, fd, (u_int32_t*)data); break; case SIS1100_JTAG_DATA: res=ioctl_jtag_data(sc, fd, (u_int32_t*)data); break; case SIS1100_JTAG_PUT: res=ioctl_jtag_put(sc, fd, (u_int32_t*)data); break; case SIS1100_JTAG_GET: res=ioctl_jtag_get(sc, fd, (u_int32_t*)data); break; default: res=ENOTTY; break; } return res; } #ifdef __NetBSD__ int sis1100_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct sis1100_softc* sc=SIS1100SC(dev); struct sis1100_fdata* fd=SIS1100FD(dev); fd->p=p; return _sis1100_ioctl(sc, fd, cmd, data); } #elif __linux__ union alles { struct vmespace vmespace; struct sis1100_vme_req vme_req; struct sis1100_vme_block_req vme_block_req; struct sis1100_ctrl_reg ctrl_reg; struct sis1100_pipe pipe; struct sis1100_ident ident; struct sis1100_irq_ctl irq_ctl; struct sis1100_irq_get irq_get; struct sis1100_irq_ack irq_ackirq_ack; struct sis1100_vme_super_block_req vme_super_block_req; struct sis1100_writepipe writepipe; struct sis1100_dma_alloc dma_alloc; struct sis1100_camac_req camac_req; struct sis1100_dsp_code dsp_code; struct sis1100_eeprom_req eeprom_req; }; #define MAX_DATA (sizeof(union alles)) int sis1100_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct sis1100_softc* sc=SIS1100SC(file); struct sis1100_fdata* fd=SIS1100FD(file); u_int8_t data[MAX_DATA]; int res; if ((cmd&IOC_INOUT) && (_IOC_SIZE(cmd)>MAX_DATA)) { pINFO(sc, "sis1100_ioctl: cmd=0x%08x _IOC_SIZE(cmd)=%d", cmd, _IOC_SIZE(cmd)); return -EINVAL; } if (cmd&IOC_IN) { if (copy_from_user(&data, (void *)arg, _IOC_SIZE(cmd))) return -EFAULT; } if ((res=_sis1100_ioctl(sc, fd, cmd, &data))) return -res; if (cmd&IOC_OUT) { if (copy_to_user((void *)arg, &data, _IOC_SIZE(cmd))) return -EFAULT; } return 0; } #endif