summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1994-09-21 01:29:41 +0000
committerjkh <jkh@FreeBSD.org>1994-09-21 01:29:41 +0000
commitca5df8fb1c2c869a2c2e1d57be8897929e6ae530 (patch)
tree0f864dcf95ade5c122e4f456d8d216adaf26b38b /sys/i386
parent3a54057ede37867a7368e99feeae8ad3e3248382 (diff)
downloadFreeBSD-src-ca5df8fb1c2c869a2c2e1d57be8897929e6ae530.zip
FreeBSD-src-ca5df8fb1c2c869a2c2e1d57be8897929e6ae530.tar.gz
Add the transputer driver from Christoph Niemann, Luigi Rizzo and
Lorenzo Vicisano Reviewed by: jkh Submitted by: luigi
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/isa/b004.c605
-rw-r--r--sys/i386/isa/b004.h153
2 files changed, 758 insertions, 0 deletions
diff --git a/sys/i386/isa/b004.c b/sys/i386/isa/b004.c
new file mode 100644
index 0000000..bdd0902
--- /dev/null
+++ b/sys/i386/isa/b004.c
@@ -0,0 +1,605 @@
+/*
+ * FreeBSD device driver for B004-compatible Transputer boards.
+ *
+ * based on Linux version Copyright (C) 1993 by Christoph Niemann
+ *
+ * Rewritten for FreeBSD by
+ * Luigi Rizzo (luigi@iet.unipi.it) and
+ * Lorenzo Vicisano (l.vicisano@iet.unipi.it)
+ * Dipartimento di Ingegneria dell'Informazione
+ * Universita` di Pisa
+ * via Diotisalvi 2, 56126 Pisa, ITALY
+ * 14 september 1994
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christoph Niemann,
+ * Luigi Rizzo and Lorenzo Vicisano - Dipartimento di Ingegneria
+ * dell'Informazione
+ * 4. The names of these contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ *
+ * NOTE NOTE NOTE
+ * The assembler version is still under development.
+ */
+
+/* #define USE_ASM */
+
+#include "bqu.h"
+#if NBQU > 0
+
+#include <sys/param.h>
+#include <sys/systm.h> /* for min(), SELWAIT */
+/* #include "proc.h" /* for pid_t */
+/* #include "user.h" */
+/* #include "buf.h" */
+/* #include "kernel.h" */
+#include <sys/uio.h>
+/* #include "sys/ioctl.h" */
+/* #include "syslog.h" */
+
+#include <i386/isa/isa_device.h>
+#include <sys/errno.h>
+
+#include "b004.h"
+
+#define IOCTL_OUT(arg, ret) *(int*)arg = ret
+
+#define B004PRI (PZERO+8)
+
+#define B004_CHANCE 8
+
+/*
+ * Define these symbols if you want to debug the code.
+ */
+#undef B004_DEBUG
+#undef B004_DEBUG_2
+
+#ifdef B004_DEBUG
+#define out(port,data) d_outb(port, data)
+#define in(a) d_inb(((u_int)a))
+#else
+#define out(port, data) outb(port,data)
+#define in(port) inb(((u_int)port))
+#endif B004_DEBUG
+
+#ifdef B004_DEBUG
+#define DEB(x) x
+#define NO_DEB(x) /* */
+#else
+#define DEB(x) /* */
+#define NO_DEB(x) x
+#endif
+
+#ifdef B004_DEBUG_2
+#define DEB2(x) x
+#else
+#define DEB2(x)
+#endif
+
+int bquclose(dev_t dev, int flag);
+int bquopen(dev_t dev, int flag);
+int bquwrite(dev_t dev, struct uio *uio, int flag);
+int bquread(dev_t dev, struct uio *uio, int flag);
+int bquioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
+int bquselect(dev_t dev, int rw, struct proc *p);
+int bquprobe(struct isa_device *idp);
+int bquattach(struct isa_device *idp);
+
+
+struct isa_driver bqudriver = {
+ bquprobe, bquattach, "bqu"
+};
+
+static int b004_sleep; /* wait address */
+
+static struct b004_struct b004_table[NBQU];
+
+static int first_time=1;
+
+/*
+ * At these addresses the driver will search for B004-compatible boards
+ */
+static int
+b004_base_addresses[B004_CHANCE] = {
+ /* 0x150, 0x170, 0x190, 0x200, 0x300, 0x320, 0x340, 0x360 */
+ 0x150, 0x190, 0, 0, 0, 0, 0, 0
+};
+
+
+void
+d_outb(u_int port, u_char data)
+{
+
+ printf("OUT 0x%x TO 0x%x\n",data,port);
+ outb(port,data);
+}
+
+u_char d_inb(u_int port)
+{
+u_char ap;
+ ap=inb(port);
+ printf("INPUT 0x%x FROM 0x%x\n",ap,port);
+ return(ap);
+}
+
+static int
+detected(int base)
+{
+ int i;
+ for(i=0;i<NBQU;i++)
+ if ((B004_F(i) & B004_EXIST) && (B004_BASE(i)==base)) return 1;
+ return (0);
+}
+
+#define b004_delay(a) DELAY(10000)
+
+/*
+ * static void bqureset(): reset transputer network.
+ *
+ */
+
+static void
+bqureset( const int dev_min )
+{
+ DEB(printf("B004 resetting transputer at link %d.\n", dev_min);)
+ out(B004_BASE(dev_min)+B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE);
+ b004_delay(dev_min);
+
+ out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET);
+ b004_delay(dev_min);
+
+ out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_ASSERT_RESET);
+ b004_delay(dev_min);
+
+ out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET);
+ b004_delay(dev_min);
+
+ DEB(printf("B004 reset done.\n");)
+}
+
+/*
+ * static void bquanalyse(): switch transputer network to analyse mode.
+ *
+ */
+
+static void
+bquanalyse( const int dev_min )
+{
+ DEB(printf("B004 analysing transputer at link %d.\n", dev_min);)
+
+ out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE);
+ b004_delay(dev_min);
+
+ out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_ASSERT_ANALYSE);
+ b004_delay(dev_min);
+
+ out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_ASSERT_RESET);
+ b004_delay(dev_min);
+
+ out(B004_BASE(dev_min) + B004_RESET_OFFSET, B004_DEASSERT_RESET);
+ b004_delay(dev_min);
+
+ out(B004_BASE(dev_min) + B004_ANALYSE_OFFSET, B004_DEASSERT_ANALYSE);
+ b004_delay(dev_min);
+
+ DEB(printf("B004 switching to analyse-mode done.\n");)
+}
+
+
+/****************************************************************************
+ *
+ * int bquread() - read bytes from the link interface.
+ *
+ * At first, the driver checks if the link-interface is ready to send a byte
+ * to the PC. If not, this check is repeated up to B004_MAXTRY times.
+ * If the link-interface is not ready after this loop, the driver sleeps for
+ * an NO=1 ticks and then checks the link-interface again.
+ * If the interface is still not ready, repeats as above incrementing NO.
+ * Once almost one byte is read N0 is set to 1.
+ * If B004_TIMEOUT != 0 and the link-interface is not ready for more than
+ * B004_TIMEOUT ticks read aborts returnig with the number of bytes read
+ * or with an error if no byte was read.
+ *
+ * By default, B004_TIMEOUT is = 0 (read is blocking)
+ *
+ *****************************************************************************/
+
+int
+bquread(dev_t dev, struct uio *uio, int flag)
+{
+ unsigned int dev_min = minor(dev) & 7;
+
+ int timeout=B004_TIMEOUT(dev_min);
+ int Timeout=timeout;
+ int idr=B004_IDR(dev_min);
+ int isr=B004_ISR(dev_min);
+ char buffer[B004_MAX_BYTES];
+
+ if ( uio->uio_resid < 0) {
+ DEB(printf("B004: invalid count for reading = %d.\n", uio->uio_resid);)
+ return EINVAL;
+ }
+
+ while ( uio->uio_resid ) {
+ int sleep_ticks=0;
+ char *p, *last, *lim;
+ int i, end = min(B004_MAX_BYTES,uio->uio_resid);
+ lim= &buffer[end];
+ for (p= buffer; p<lim;) {
+ last=p;
+ /*** try to read as much as possible ***/
+#ifdef USE_ASM
+ /* assembly code uses a very tight loop, with
+ * BX= data port, DX= address port, CX=count, ES:DI=p, AL=data, AH=1
+ * SI=retry counter
+ */
+ __asm__ (
+ "movl %1, %%edx\n\t" /* isr */
+ "movl %2, %%ebx\n\t" /* idr */
+ "movl %3, %%edi\n" /* p */
+ "movl %4, %%ecx\n\t" /* lim */
+ "subl %%edi, %%ecx\n\t"
+
+ "push %%es\n\t"
+ "movw %%ss, %%ax\n\t" /** prepare ES, DF for transfer */
+ "movw %%ax, %%es\n\t"
+ "cld\n\t"
+ "movb $1, %%ah\n\t"
+
+ "1:\tinb %%dx, %%al\n\t"
+ "testb %%ah, %%al\n\t"
+ "jz 2f\n\t"
+ "xchgl %%edx, %%ebx\n\t"
+ "insb\n\t"
+ "xchgl %%edx, %%ebx\n"
+ "2:\tloop 1b\n\t"
+
+ "pop %%es\n\t"
+ "movl %%edi, %0\n\t" /* store p */
+ : /* out */ "=g" (p)
+ : /* in */ "g" (isr), "g" (idr), "g" (p), "g" (lim)
+ : /* regs */ "eax", "ebx", "edx", "ecx", "edi");
+#else
+ for (i=lim - p; i-- ;)
+ if (inb(isr)&B004_READBYTE) *p++ =(char) inb(idr);
+#endif
+ if (last!=p) {
+ sleep_ticks = 0;
+ } else {
+ /*** no new data read, must sleep ***/
+ sleep_ticks= (sleep_ticks<20 ? sleep_ticks+1 : sleep_ticks);
+ if (Timeout) {
+ if (timeout <=0) {
+ DEB2(printf("Read : TIMEOUT OCCURRED XXXXXXXXXXX\n");)
+ break;
+ }
+ if (timeout < sleep_ticks) sleep_ticks=timeout;
+ timeout -= sleep_ticks;
+ }
+ DEB2(printf("Read: SLEEPING FOR %d TICKS XXXXX\n",sleep_ticks);)
+ if (tsleep((caddr_t)&b004_sleep, B004PRI | PCATCH,
+ "b004_rd", sleep_ticks)!=EWOULDBLOCK) return 1;
+ }
+ }
+ if (p != buffer) {
+ uiomove((caddr_t)buffer, p - buffer, uio);
+ }
+ if( (Timeout) && (timeout <= 0) )
+ break;
+ }
+ return 0;
+} /* bquread() */
+
+
+/*
+ * int bquwrite() - write to the link interface.
+ */
+
+int
+bquwrite(dev_t dev, struct uio *uio, int flag)
+{
+ unsigned int dev_min = minor(dev) & 7;
+
+ int i, end;
+ int timeout=B004_TIMEOUT(dev_min);
+ int Timeout=timeout;
+ int odr=B004_ODR(dev_min);
+ int osr=B004_OSR(dev_min);
+ char buffer[B004_MAX_BYTES];
+
+ if ( uio->uio_resid < 0) {
+ DEB(printf("B004 invalid argument for writing: count = %d.\n", uio->uio_resid);)
+ return EINVAL;
+ }
+
+ while ( uio->uio_resid ) {
+ int sleep_ticks=0;
+ char *p, *last, *lim;
+ end = min(B004_MAX_BYTES,uio->uio_resid);
+ uiomove((caddr_t)buffer, end, uio);
+
+ lim= &buffer[end];
+ for (p= &buffer[0]; p<lim;) {
+ last=p;
+#ifdef USE_ASM
+ /* assembly code uses a very tight loop, with
+ * BX= data port, DX= address port, CX=count, DS:SI=p, AL=data, AH=1
+ * DI= retry counter
+ * Unfortunately, C is almost as fast as this!
+ */
+ __asm__ (
+ "movl %1, %%edx\n\t" /* osr */
+ "movl %2, %%ebx\n\t" /* odr */
+ "movl %3, %%esi\n" /* p */
+ "movl %4, %%ecx\n\t" /* lim */
+ "subl %%esi, %%ecx\n\t"
+
+ "push %%ds\n\t"
+ "movw %%ss, %%ax\n\t" /** prepare DS, DF for transfer */
+ "movw %%ax, %%ds\n\t"
+ "cld\n\t"
+ "movb $1, %%ah\n\t"
+ "movw $100, %%di\n\t"
+
+ "1:\tinb %%dx, %%al\n\t"
+ "testb %%ah, %%al\n\t"
+ "jz 2f\n\t"
+ "xchgl %%edx, %%ebx\n\t"
+ "outsb\n\t"
+ "xchgl %%edx, %%ebx\n\t"
+ "loop 1b\n\t"
+ "jmp 3f\n"
+
+ "2:\tdec %%di\n\t"
+ "jnc 1b\n\t"
+
+ "3:\tpop %%ds\n"
+ "movl %%esi, %0\n\t" /* store p */
+ : /* out */ "=g" (p)
+ : /* in */ "g" (osr), "g" (odr), "g" (p), "g" (lim)
+ : /* regs */ "eax", "ebx", "edx", "ecx", "esi", "edi");
+#else
+ for (i=lim - p; i-- ; ) {
+ if (inb(osr)&B004_WRITEBYTE) outb(odr, *p++);
+ }
+#endif
+ if (p != last ) {
+ sleep_ticks=0;
+ } else {
+ sleep_ticks= (sleep_ticks<20 ? sleep_ticks+1 : sleep_ticks);
+ if (Timeout) {
+ if (timeout <=0) {
+ DEB2(printf("Write : TIMEOUT OCCURRED XXXXXXXXXXX\n");)
+ uio->uio_resid += (lim - p);
+ break;
+ }
+ if (timeout < sleep_ticks) sleep_ticks=timeout;
+ timeout -= sleep_ticks;
+ }
+ DEB2(printf("Write: SLEEPING FOR %d TICKS XXXXXXX\n",sleep_ticks);)
+ if (tsleep((caddr_t)&b004_sleep, B004PRI | PCATCH,
+ "b004_rd", sleep_ticks)!=EWOULDBLOCK) return 1;
+ }
+ }
+ if( (Timeout) && (timeout <= 0) )
+ break;
+ }
+ return 0;
+} /* bquwrite() */
+
+/*
+ * int bquopen() -- open the link-device.
+ *
+ */
+
+int
+bquopen(dev_t dev, int flag)
+{
+ unsigned int dev_min = minor(dev) & 7;
+
+ if (dev_min >= NBQU) {
+ DEB(printf("B004 not opened, minor number >= %d.\n", NBQU);)
+ return ENXIO;
+ }
+ if ((B004_F(dev_min) & B004_EXIST) == 0) {
+ DEB(printf("B004 not opened, board %d does not exist.\n", dev_min);)
+ return ENXIO;
+ }
+ if (B004_F(dev_min) & B004_BUSY) {
+ DEB(printf("B004 not opened, board busy (minor = %d).\n", dev_min);)
+ return EBUSY;
+ }
+ B004_F(dev_min) |= B004_BUSY;
+ B004_TIMEOUT(dev_min) = 0;
+ DEB(printf( "B004 opened, minor = %d.\n", dev_min );)
+ return 0;
+} /* bquopen() */
+
+
+/*
+ * int b004close() -- close the link device.
+ */
+
+int
+bquclose(dev_t dev, int flag)
+{
+ unsigned int dev_min = minor(dev) & 7;
+
+ if (dev_min >= NBQU) {
+ DEB(printf("B004 not released, minor number >= %d.\n", NBQU);)
+ return ENXIO;
+ }
+ B004_F(dev_min) &= ~B004_BUSY;
+ DEB(printf("B004(%d) released.\n", dev_min );)
+ return 0;
+}
+
+int
+bquselect(dev_t dev, int rw, struct proc *p)
+{
+ /* still unimplemented */
+ return(1);
+}
+
+/*
+ * int bquioctl()
+ *
+ * Supported functions:
+ * - reset
+ * - analyse
+ * - test error flag
+ * - set timeout
+ */
+
+int
+bquioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ unsigned int dev_min = minor(dev) & 7;
+ int result = 0;
+
+ if (dev_min >= NBQU) {
+ DEB(printf("B004 ioctl exit, minor >= %d.\n", NBQU );)
+ return ENODEV;
+ }
+
+ if ((B004_F(dev_min) & B004_EXIST) == 0) {
+ DEB(printf("B004 ioctl exit, (B004_F & B004_EXIST) == 0.\n" );)
+ return ENODEV;
+ }
+
+ switch ( cmd ) {
+ case B004RESET: /* reset transputer */
+ bqureset(dev_min);
+ DEB(printf("B004 ioctl B004RESET, done\n" );)
+ break;
+ case B004WRITEABLE: /* can we write a byte to the C012 ? */
+ IOCTL_OUT (addr, ((in(B004_OSR(dev_min))&B004_WRITEBYTE) != 0 ));
+ break;
+ case B004READABLE: /* can we read a byte from C012 ? */
+ IOCTL_OUT (addr, ((in(B004_ISR(dev_min)) & B004_READBYTE) != 0 ));
+ break;
+ case B004ANALYSE: /* switch transputer to analyse mode */
+ bquanalyse(dev_min);
+ break;
+ case B004ERROR: /* test error-flag */
+ IOCTL_OUT (addr,
+ ((inb(B004_BASE(dev_min)+B004_ERROR_OFFSET) &
+ B004_TEST_ERROR) ? 0 : 1));
+ break;
+ case B004TIMEOUT: /* set, retrieve timeout for writing & reading*/
+ B004_TIMEOUT(dev_min) = *((int *)addr);
+ break;
+ default: result = EINVAL;
+ }
+ return result;
+} /* bquioctl() */
+
+int
+bquattach(struct isa_device *idp)
+{
+ return 1;
+}
+
+/*
+ * int bquprobe
+ *
+ * Initializes the driver. It tries to detect the hardware
+ * and sets up all relevant data-structures.
+ */
+
+int
+bquprobe(struct isa_device *idp)
+{
+ unsigned int test;
+ unsigned int dev_min = idp->id_unit;
+ int i,found = 0;
+ /* After a reset it should be possible to write a byte to
+ the B004. So let'S do a reset and then test the output status
+ register
+ */
+#ifdef undef
+printf("bquprobe::\nIOBASE 0x%x\nIRQ %d\nDRQ %d\nMSIZE %d\nUNIT %d\nFLAGS x0%x\nALIVE %d\n",idp->id_iobase,idp->id_irq,idp->id_drq,idp->id_msize,idp->id_unit,idp->id_flags,idp->id_alive);
+#endif
+ if(first_time){
+ for(i=0;i<NBQU;i++) B004_F(i) &= ~B004_EXIST;
+ first_time=0;
+ }
+
+ if(dev_min >= NBQU) return (0); /* No more descriptors */
+ if ((idp->id_iobase < 0x100) || (idp->id_iobase >= 0x1000))
+ idp->id_iobase=0; /* Dangerous isa addres ) */
+ for (test = 0; (test < B004_CHANCE); test++) {
+ if((idp->id_iobase==0)&&((!b004_base_addresses[test])||
+ detected(b004_base_addresses[test])))
+ continue;
+ idp->id_iobase=b004_base_addresses[test];
+
+ DEB(printf("Probing device %d at address 0x%x\n",dev_min,
+ idp->id_iobase);
+ )
+ b004_delay(test);
+ B004_F(dev_min) = 0;
+ B004_TIMEOUT(dev_min) = B004_INIT_TIMEOUT;
+ B004_BASE(dev_min) = idp->id_iobase;
+ B004_ODR(dev_min) = B004_BASE(dev_min) + B004_ODR_OFFSET;
+ B004_ISR(dev_min) = B004_BASE(dev_min) + B004_ISR_OFFSET;
+ B004_OSR(dev_min) = B004_BASE(dev_min) + B004_OSR_OFFSET;
+ bqureset(dev_min);
+
+ for (i = 0; i < B004_MAXTRY; i++)
+ if ( in(B004_OSR(dev_min)) == B004_WRITEBYTE) {
+ B004_F(dev_min) |= B004_EXIST;
+ out(B004_BASE(dev_min) + B008_INT_OFFSET, 0);
+ b004_delay(test);
+ if (in(B004_BASE(dev_min) + B008_INT_OFFSET) & 0x0f == 0)
+ B004_BOARDTYPE(dev_min) = B008;
+ else
+ B004_BOARDTYPE(dev_min) = B004;
+ printf("bqu%d at 0x0%x (polling) is a B00%s\n",
+ dev_min,B004_IDR(dev_min),
+ (B004_BOARDTYPE(dev_min) == B004) ? "4" : "8");
+ found = 1;
+ break;
+ }
+ if(!found) {
+ idp->id_iobase=0;
+ }
+ else break;
+
+ }
+
+ if (!found){
+ printf("b004probe(): no B004-board found.\n");
+ return (0);
+ }
+
+ idp->id_maddr=NULL;
+ idp->id_irq=0;
+ if(B004_BOARDTYPE(dev_min) == B004)
+ return(18);
+ else
+ return(20);
+} /* bquprobe() */
+
+#endif /* NBQU */
diff --git a/sys/i386/isa/b004.h b/sys/i386/isa/b004.h
new file mode 100644
index 0000000..8c82eda
--- /dev/null
+++ b/sys/i386/isa/b004.h
@@ -0,0 +1,153 @@
+#ifndef _B004_H
+#define _B004_H
+
+/*
+ * b004.h
+ *
+ * Based on the Linux driver, by
+ * Christoph Niemann (niemann@swt.ruhr-uni-bochum.de)
+ *
+ * Ported to FreeBSD by Luigi Rizzo (luigi@iet.unipi.it)
+ * and Lorenzo Vicisano (l.vicisano@iet.unipi.it)
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christoph Niemann,
+ * Luigi Rizzo and Lorenzo Vicisano - Dipartimento di Ingegneria
+ * dell'Informazione
+ * 4. The names of these contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 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.
+ *
+ * Works for FreeBSD 1.1.5
+ */
+
+#include <sys/ioctl.h>
+
+/*
+ * device status FLAGS
+ */
+#define B004_EXIST 0x0001 /* Is a B004-Board with at least one
+ Transputer present ? */
+#define B004_BUSY 0x0002 /* Is the B004-board in use ? */
+
+/*
+ * IOCTL numbers
+ */
+#define B004RESET _IO ('Q', 0)
+ /* Reset transputer(s) */
+#define B004WRITEABLE _IOR ('Q', 1, int)
+ /* Return C012 Output Ready */
+#define B004READABLE _IOR ('Q', 2, int)
+ /* Return C012 Data Present */
+#define B004ANALYSE _IO ('Q', 3)
+ /* Switch transputer(s) to ANALYSE mode */
+#define B004ERROR _IOR ('Q', 4, int)
+ /* Return 1 on ERROR set */
+#define B004TIMEOUT _IOW ('Q', 5, int)
+ /* Set TIMEOUT for subsequent writing or
+ reading call, value in ticks, initial
+ 0 = no timeout (read/write blocking)
+ "open" sets timeout to 0 */
+
+
+#define B004_INIT_TIMEOUT 0 /* No timeout yet */
+
+/*
+ * Registers DISPLACEMENT
+ */
+#define B004_IDR_OFFSET 0 /* Input Data Register */
+#define B004_ODR_OFFSET 1 /* Output Data Register */
+#define B004_ISR_OFFSET 2 /* Input Status Register */
+#define B004_OSR_OFFSET 3 /* Output Status Register */
+#define B004_RESET_OFFSET 16 /* Reset/Error Register */
+#define B004_ERROR_OFFSET B004_RESET_OFFSET
+#define B004_ANALYSE_OFFSET 17 /* Analyse Register */
+#define B008_DMA_OFFSET 18 /* B008: DMA request register */
+#define B008_INT_OFFSET 19 /* B008: Interrupt control reg */
+
+struct b004_struct {
+ int flags; /* various flags */
+ int idr; /* address of the input data register */
+ int odr; /* address if the output data register */
+ int isr; /* address of the input status register */
+ int osr; /* address of the output status register */
+ unsigned int timeout; /* timeout for writing/reading the link */
+ int boardtype; /* what kind of board is installed */
+};
+
+/*
+ * Id's for the supported boards
+ */
+#define B004 1
+#define B008 2
+
+/*
+ * Defines for easier access to the b004_table.
+ */
+#define B004_F(minor) b004_table[minor].flags
+#define B004_TIMEOUT(minor) b004_table[minor].timeout
+#define B004_BASE(minor) B004_IDR(minor)
+#define B004_IDR(minor) b004_table[minor].idr
+#define B004_ODR(minor) b004_table[minor].odr
+#define B004_ISR(minor) b004_table[minor].isr
+#define B004_OSR(minor) b004_table[minor].osr
+#define B004_WAIT(minor) b004_table[minor].wait
+#define B004_BOARDTYPE(minor) b004_table[minor].boardtype
+
+/*
+ * Additonal defines for B008-boards
+ */
+#define B008_DMA(minor) b004_table[minor].int
+#define B008_INT(minor) b004_table[minor].dma
+
+/*
+ * Number of tries to access isr or osr before reading or writing sleeps
+ */
+#define B004_MAXTRY 200
+
+/*
+ * Maximum number of bytes to transfer at once
+ */
+#define B004_MAX_BYTES 2048
+
+/*
+ * bit defines for C012 status ports at base + 2/3
+ * accessed with B004_IS, B004_OS, which gets the byte...
+ */
+#define B004_READBYTE 1
+#define B004_WRITEBYTE 1
+
+/*
+ * bit defines for C012 reset/error port at base + 16
+ */
+#define B004_ASSERT_RESET 0x01 /* resetting the transputer */
+#define B004_DEASSERT_RESET 0x00
+#define B004_TEST_ERROR 0x01 /* for testing the transputer's error flag */
+
+/*
+ * bit defines for C012 analyse port at base + 17
+ */
+#define B004_ASSERT_ANALYSE 0x01 /* switch transputer to analyse-mode */
+#define B004_DEASSERT_ANALYSE 0x00
+
+#endif
OpenPOWER on IntegriCloud