From ca5df8fb1c2c869a2c2e1d57be8897929e6ae530 Mon Sep 17 00:00:00 2001 From: jkh Date: Wed, 21 Sep 1994 01:29:41 +0000 Subject: [PATCH] Add the transputer driver from Christoph Niemann, Luigi Rizzo and Lorenzo Vicisano Reviewed by: jkh Submitted by: luigi --- sys/i386/isa/b004.c | 605 ++++++++++++++++++++++++++++++++++++++++++++ sys/i386/isa/b004.h | 153 +++++++++++ 2 files changed, 758 insertions(+) create mode 100644 sys/i386/isa/b004.c create mode 100644 sys/i386/isa/b004.h diff --git a/sys/i386/isa/b004.c b/sys/i386/isa/b004.c new file mode 100644 index 000000000000..bdd0902033ce --- /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 +#include /* for min(), SELWAIT */ +/* #include "proc.h" /* for pid_t */ +/* #include "user.h" */ +/* #include "buf.h" */ +/* #include "kernel.h" */ +#include +/* #include "sys/ioctl.h" */ +/* #include "syslog.h" */ + +#include +#include + +#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;iuio_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; puio_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]; puio_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) 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 000000000000..8c82edafbe93 --- /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 + +/* + * 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