aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan K. Hubbard <jkh@FreeBSD.org>1995-01-07 14:52:08 +0000
committerJordan K. Hubbard <jkh@FreeBSD.org>1995-01-07 14:52:08 +0000
commit2f6df2645b49b846a6d15262a2958692fe618f56 (patch)
tree1372065193c766f5d416c6b76c3492668c856aa4
parent349257ffa617ef4c6fa99ea814ef9c230042d63d (diff)
downloadsrc-2f6df2645b49b846a6d15262a2958692fe618f56.tar.gz
src-2f6df2645b49b846a6d15262a2958692fe618f56.zip
Gunther Schadow <gusw@fub46.zedat.fu-berlin.de>'s
driver for the Genius GS-4500 hand scanner. Submitted by: gusw@fub46.zedat.fu-berlin.de
Notes
Notes: svn path=/head/; revision=5428
-rw-r--r--etc/MAKEDEV9
-rw-r--r--etc/etc.i386/MAKEDEV9
-rw-r--r--sys/amd64/isa/isa.h9
-rw-r--r--sys/conf/NOTES6
-rw-r--r--sys/conf/files.i3863
-rw-r--r--sys/i386/conf/LINT6
-rw-r--r--sys/i386/conf/NOTES6
-rw-r--r--sys/i386/conf/files.i3863
-rw-r--r--sys/i386/i386/conf.c19
-rw-r--r--sys/i386/include/gsc.h52
-rw-r--r--sys/i386/isa/gsc.c774
-rw-r--r--sys/i386/isa/gscreg.h87
-rw-r--r--sys/i386/isa/isa.h9
13 files changed, 973 insertions, 19 deletions
diff --git a/etc/MAKEDEV b/etc/MAKEDEV
index ba42148f045d..a91b0bdf55fb 100644
--- a/etc/MAKEDEV
+++ b/etc/MAKEDEV
@@ -71,8 +71,9 @@
# pcaudio PCM audio driver
# socksys iBCS2 socket system driver
# vat VAT compatibility audio driver (requires snd*)
+# gsc Genius GS-4500 hand scanner
#
-# $Id: MAKEDEV,v 1.60 1994/12/16 15:59:44 bde Exp $
+# $Id: MAKEDEV,v 1.61 1994/12/25 15:08:29 ats Exp $
#
PATH=/sbin:/bin/:/usr/bin:/usr/sbin:
@@ -649,6 +650,12 @@ vat)
chmod 660 vatio
;;
+gsc)
+ rm -f gsc0
+ mknod gsc0 c 47 0
+ chmod 666 gsc0
+ ;;
+
apm)
rm -f apm0
mknod apm0 c 39 0
diff --git a/etc/etc.i386/MAKEDEV b/etc/etc.i386/MAKEDEV
index ba42148f045d..a91b0bdf55fb 100644
--- a/etc/etc.i386/MAKEDEV
+++ b/etc/etc.i386/MAKEDEV
@@ -71,8 +71,9 @@
# pcaudio PCM audio driver
# socksys iBCS2 socket system driver
# vat VAT compatibility audio driver (requires snd*)
+# gsc Genius GS-4500 hand scanner
#
-# $Id: MAKEDEV,v 1.60 1994/12/16 15:59:44 bde Exp $
+# $Id: MAKEDEV,v 1.61 1994/12/25 15:08:29 ats Exp $
#
PATH=/sbin:/bin/:/usr/bin:/usr/sbin:
@@ -649,6 +650,12 @@ vat)
chmod 660 vatio
;;
+gsc)
+ rm -f gsc0
+ mknod gsc0 c 47 0
+ chmod 666 gsc0
+ ;;
+
apm)
rm -f apm0
mknod apm0 c 39 0
diff --git a/sys/amd64/isa/isa.h b/sys/amd64/isa/isa.h
index cec13f6b5d97..453b3a5ae4ba 100644
--- a/sys/amd64/isa/isa.h
+++ b/sys/amd64/isa/isa.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.h 5.7 (Berkeley) 5/9/91
- * $Id: isa.h,v 1.10 1994/11/19 18:47:57 phk Exp $
+ * $Id: isa.h,v 1.11 1994/11/19 18:59:04 phk Exp $
*/
#ifndef _I386_ISA_ISA_H_
@@ -79,12 +79,13 @@
#define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */
#define IO_GAME 0x200 /* Game Controller */
- /* 0x208 - 0x277 Open */
+#define IO_GSC1 0x270 /* -- 0x27B! GeniScan GS-4500 addr.grp. 1 */
+#define IO_GSC2 0x2e0 /* GeniScan GS-4500 addr.grp. 2 */
+#define IO_GSC3 0x370 /* GeniScan GS-4500 addr.grp. 3 */
+#define IO_GSC4 0x3e0 /* GeniScan GS-4500 addr.grp. 4 */
#define IO_LPT2 0x278 /* Parallel Port #2 */
- /* 0x280 - 0x2E7 Open */
-
#define IO_COM4 0x2e8 /* COM4 i/o address */
/* 0x2F0 - 0x2F7 Open */
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index bd69a77273f9..0354fdc737d3 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.121 1994/12/22 21:00:02 wollman Exp $
+# $Id: LINT,v 1.122 1994/12/26 17:33:52 ats Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -434,19 +434,21 @@ tape ft0 at fdc0 drive 2
options FDSEEKWAIT="16"
#
-# Other standard PC hardware: `lpt', `mse', `psm', `sio'
+# Other standard PC hardware: `lpt', `mse', `psm', `sio', etc.
#
# lpt: printer port
# mse: Logitech and ATI InPort bus mouse ports
# psm: PS/2 mouse port (needs ALLOW_CONFLICT_IOADDR, above)
# sio: serial ports (see sio(4))
# gp: National Instruments AT-GPIB and AT-GPIB/TNT board
+# gsc: Genius GS-4500 hand scanner.
device lpt0 at isa? port "IO_LPT3" tty irq 7 vector lptintr
device mse0 at isa? port 0x23c tty irq 5 vector mseintr
device psm0 at isa? port "IO_KBD" tty irq 12 vector psmintr
device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr
device gp0 at isa? port 0x2c0 tty
+device gsc0 at isa? port "IO_GSC1" tty drq 3
# Options for sio:
options COMCONSOLE #prefer serial console to video console
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 1fadb793d281..f9a8f7cdfb25 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.67 1994/12/26 01:06:41 ats Exp $
+# $Id: files.i386,v 1.68 1994/12/31 19:27:29 gibbs Exp $
#
i386/apm/apm.c optional apm device-driver
i386/apm/apm_setup.s optional apm
@@ -69,6 +69,7 @@ i386/isa/ft.c optional ft device-driver
i386/isa/elink.c optional ie device-driver
i386/isa/elink.c optional ep device-driver
i386/isa/gpib.c optional gp device-driver
+i386/isa/gsc.c optional gsc device-driver
i386/isa/if_cx.c optional cx device-driver
i386/isa/if_ed.c optional ed device-driver
i386/isa/if_el.c optional el device-driver
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index bd69a77273f9..0354fdc737d3 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.121 1994/12/22 21:00:02 wollman Exp $
+# $Id: LINT,v 1.122 1994/12/26 17:33:52 ats Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -434,19 +434,21 @@ tape ft0 at fdc0 drive 2
options FDSEEKWAIT="16"
#
-# Other standard PC hardware: `lpt', `mse', `psm', `sio'
+# Other standard PC hardware: `lpt', `mse', `psm', `sio', etc.
#
# lpt: printer port
# mse: Logitech and ATI InPort bus mouse ports
# psm: PS/2 mouse port (needs ALLOW_CONFLICT_IOADDR, above)
# sio: serial ports (see sio(4))
# gp: National Instruments AT-GPIB and AT-GPIB/TNT board
+# gsc: Genius GS-4500 hand scanner.
device lpt0 at isa? port "IO_LPT3" tty irq 7 vector lptintr
device mse0 at isa? port 0x23c tty irq 5 vector mseintr
device psm0 at isa? port "IO_KBD" tty irq 12 vector psmintr
device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr
device gp0 at isa? port 0x2c0 tty
+device gsc0 at isa? port "IO_GSC1" tty drq 3
# Options for sio:
options COMCONSOLE #prefer serial console to video console
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index bd69a77273f9..0354fdc737d3 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.121 1994/12/22 21:00:02 wollman Exp $
+# $Id: LINT,v 1.122 1994/12/26 17:33:52 ats Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -434,19 +434,21 @@ tape ft0 at fdc0 drive 2
options FDSEEKWAIT="16"
#
-# Other standard PC hardware: `lpt', `mse', `psm', `sio'
+# Other standard PC hardware: `lpt', `mse', `psm', `sio', etc.
#
# lpt: printer port
# mse: Logitech and ATI InPort bus mouse ports
# psm: PS/2 mouse port (needs ALLOW_CONFLICT_IOADDR, above)
# sio: serial ports (see sio(4))
# gp: National Instruments AT-GPIB and AT-GPIB/TNT board
+# gsc: Genius GS-4500 hand scanner.
device lpt0 at isa? port "IO_LPT3" tty irq 7 vector lptintr
device mse0 at isa? port 0x23c tty irq 5 vector mseintr
device psm0 at isa? port "IO_KBD" tty irq 12 vector psmintr
device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr
device gp0 at isa? port 0x2c0 tty
+device gsc0 at isa? port "IO_GSC1" tty drq 3
# Options for sio:
options COMCONSOLE #prefer serial console to video console
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index 1fadb793d281..f9a8f7cdfb25 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.67 1994/12/26 01:06:41 ats Exp $
+# $Id: files.i386,v 1.68 1994/12/31 19:27:29 gibbs Exp $
#
i386/apm/apm.c optional apm device-driver
i386/apm/apm_setup.s optional apm
@@ -69,6 +69,7 @@ i386/isa/ft.c optional ft device-driver
i386/isa/elink.c optional ie device-driver
i386/isa/elink.c optional ep device-driver
i386/isa/gpib.c optional gp device-driver
+i386/isa/gsc.c optional gsc device-driver
i386/isa/if_cx.c optional cx device-driver
i386/isa/if_ed.c optional ed device-driver
i386/isa/if_el.c optional el device-driver
diff --git a/sys/i386/i386/conf.c b/sys/i386/i386/conf.c
index c4d4d8a1926e..3e523e6f9f16 100644
--- a/sys/i386/i386/conf.c
+++ b/sys/i386/i386/conf.c
@@ -41,7 +41,7 @@
* SUCH DAMAGE.
*
* from: @(#)conf.c 5.8 (Berkeley) 5/12/91
- * $Id: conf.c,v 1.46 1994/12/17 08:06:10 jkh Exp $
+ * $Id: conf.c,v 1.47 1994/12/25 23:25:54 ats Exp $
*/
#include <sys/param.h>
@@ -695,6 +695,19 @@ d_ioctl_t gpioctl;
#define gpioctl (d_ioctl_t *)enxio
#endif
+#include "gsc.h"
+#if NGSC > 0
+d_open_t gscopen;
+d_close_t gscclose;
+d_rdwr_t gscread;
+d_ioctl_t gscioctl;
+#else
+#define gscopen (d_open_t *)enxio
+#define gscclose (d_close_t *)enxio
+#define gscread (d_rdwr_t *)enxio
+#define gscioctl (d_ioctl_t *)enxio
+#endif
+
/* open, close, read, write, ioctl, stop, reset, ttys, select, mmap, strat */
struct cdevsw cdevsw[] =
{
@@ -848,6 +861,10 @@ struct cdevsw cdevsw[] =
{ pcdopen, pcdclose, rawread, nowrite, /*46*/
pcdioctl, nostop, nullreset, NULL, /* panasonic cd */
seltrue, nommap, pcdstrategy },
+ { gscopen, gscclose, gscread, nowrite, /*47*/
+ gscioctl, nostop, nullreset, NULL, /* gsc */
+ seltrue, nommap, NULL },
+
};
int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
diff --git a/sys/i386/include/gsc.h b/sys/i386/include/gsc.h
new file mode 100644
index 000000000000..aa225a843880
--- /dev/null
+++ b/sys/i386/include/gsc.h
@@ -0,0 +1,52 @@
+/* gsc.h - programming interface to the scanner device driver `gsc'
+ *
+ *
+ * Copyright (c) 1995 Gunther Schadow. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Gunther Schadow.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without 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.
+ */
+
+#ifndef _GSC_IOCTL_H_
+#define _GSC_IOCTL_H_
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#define GSC_GRES _IOR('S', 1, int) /* get resolution / dpi */
+#define GSC_SRES _IOW('S', 2, int) /* set resolution / dpi */
+#define GSC_GWIDTH _IOR('S', 3, int) /* get width / pixels */
+#define GSC_SWIDTH _IOW('S', 4, int) /* set width / pixels */
+#define GSC_GHEIGHT _IOR('S', 5, int) /* get height / pixels */
+#define GSC_SHEIGHT _IOW('S', 6, int) /* set height / pixels */
+
+#define GSC_GBLEN _IOR('S', 7, int) /* get buffer length / lines */
+#define GSC_SBLEN _IOW('S', 8, int) /* set buffer length / lines */
+#define GSC_GBTIME _IOR('S', 9, int) /* get buffer timeout / s */
+#define GSC_SBTIME _IOW('S', 10, int) /* set buffer timeout / s */
+
+#define GSC_SRESSW _IO('S', 11) /* set resolution by switch */
+
+#endif
diff --git a/sys/i386/isa/gsc.c b/sys/i386/isa/gsc.c
new file mode 100644
index 000000000000..b2642202a0bc
--- /dev/null
+++ b/sys/i386/isa/gsc.c
@@ -0,0 +1,774 @@
+/* gsc.c - device driver for handy scanners
+ *
+ * Current version supports:
+ *
+ * - Genius GS-4500
+ *
+ * Copyright (c) 1995 Gunther Schadow. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Gunther Schadow.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without 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.
+ */
+
+#include "gsc.h"
+#if NGSC > 0
+
+#include "param.h"
+#include "systm.h"
+#include "proc.h"
+#include "user.h"
+#include "buf.h"
+#include "malloc.h"
+#include "kernel.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "uio.h"
+#include "syslog.h"
+
+#include "i386/isa/isa.h"
+#include "i386/isa/isa_device.h"
+#include "i386/isa/gscreg.h"
+
+#include "i386/include/gsc.h"
+
+/***********************************************************************
+ *
+ * CONSTANTS & DEFINES
+ *
+ ***********************************************************************/
+
+#define PROBE_FAIL 0
+#define PROBE_SUCCESS 1
+#define SUCCESS 0
+#define FAIL -1
+#define INVALID FAIL
+
+#define DMA1_READY 0x08
+
+#ifdef GSCDEBUG
+#define lprintf if(scu->flags & DEBUG) printf
+#else
+#define lprintf (void)
+#endif
+
+#define TIMEOUT (hz*15) /* timeout while reading a buffer - default value */
+#define LONG (hz/60) /* timesteps while reading a buffer */
+#define GSCPRI PRIBIO /* priority while reading a buffer */
+
+/***********************************************************************
+ *
+ * LAYOUT OF THE MINOR NUMBER
+ *
+ ***********************************************************************/
+
+#define UNIT_MASK 0xc0 /* unit gsc0 .. gsc3 */
+#define UNIT(x) (x >> 6)
+#define DBUG_MASK 0x20
+#define FRMT_MASK 0x18 /* output format */
+#define FRMT_RAW 0x00 /* output bits as read from scanner */
+#define FRMT_GRAY 0x10 /* output graymap (not implemented yet) */
+#define FRMT_PBM 0x08 /* output pbm format */
+#define FRMT_PGM 0x18
+
+/***********************************************************************
+ *
+ * THE GEMOMETRY TABLE
+ *
+ ***********************************************************************/
+
+#define GEOMTAB_SIZE 7
+
+const struct gsc_geom {
+ int dpi; /* dots per inch */
+ int dpl; /* dots per line */
+ int g_res; /* get resolution value (status flag) */
+ int s_res; /* set resolution value (control register) */
+} geomtab[GEOMTAB_SIZE] = {
+ { 100, 424, GSC_RES_100, GSC_CNT_424},
+ { 200, 840, GSC_RES_200, GSC_CNT_840},
+ { 300, 1264, GSC_RES_300, GSC_CNT_1264},
+ { 400, 1648, GSC_RES_400, GSC_CNT_1648},
+ { -1, 1696, -1, GSC_CNT_1696},
+ { -2, 2644, -2, GSC_CNT_2544},
+ { -3, 3648, -3, GSC_CNT_3648},
+};
+
+#define NEW_GEOM { INVALID, INVALID, INVALID, INVALID }
+
+/***********************************************************************
+ *
+ * THE TABLE OF UNITS
+ *
+ ***********************************************************************/
+
+struct _sbuf {
+ size_t size;
+ size_t poi;
+ char *base;
+};
+
+struct gsc_unit {
+ int channel; /* DMA channel */
+ int data; /* - video port */
+ int stat; /* - status port */
+ int ctrl; /* - control port */
+ int clrp; /* - clear port */
+ int flags;
+#define ATTACHED 0x01
+#define OPEN 0x02
+#define READING 0x04
+#define EOF 0x08
+#define DEBUG 0x10
+#define PBM_MODE 0x20
+ int geometry; /* resolution as geomtab index */
+ int blen; /* length of buffer in lines */
+ int btime; /* timeout of buffer in seconds/hz */
+ struct _sbuf sbuf;
+ char ctrl_byte; /* the byte actually written to ctrl port */
+ int height; /* height, for pnm modes */
+ size_t bcount; /* bytes to read, for pnm modes */
+ struct _sbuf hbuf; /* buffer for pnm header data */
+} unittab[NGSC];
+
+/* I could not find a reasonable buffer size limit other than by
+ * experiments. MAXPHYS is obviously too much, while DEV_BSIZE and
+ * PAGE_SIZE are really too small. There must be something wrong
+ * with isa_dmastart/isa_dmarangecheck HELP!!!
+ */
+#define MAX_BUFSIZE 0x3000
+#define DEFAULT_BLEN 59
+
+/***********************************************************************
+ *
+ * THE PER-DRIVER RECORD FOR ISA.C
+ *
+ ***********************************************************************/
+
+int gscprobe (struct isa_device *isdp);
+int gscattach(struct isa_device *isdp);
+
+struct isa_driver gscdriver = { gscprobe, gscattach, "gsc" };
+
+/***********************************************************************
+ *
+ * LOCALLY USED SUBROUTINES
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ *
+ * lookup_geometry -- lookup a record in the geometry table by pattern
+ *
+ * The caller supplies a geometry record pattern, where INVALID
+ * matches anything. Returns the index in the table or INVALID if
+ * lookup fails.
+ */
+
+static int
+lookup_geometry(struct gsc_geom geom, const struct gsc_unit *scu)
+{
+ struct gsc_geom tab;
+ int i;
+
+ for(i=0; i<GEOMTAB_SIZE; i++)
+ {
+ tab = geomtab[i];
+
+ if ( ( ( geom.dpi != INVALID ) && ( tab.dpi == geom.dpi ) ) ||
+ ( ( geom.dpl != INVALID ) && ( tab.dpl == geom.dpl ) ) ||
+ ( ( geom.g_res != INVALID ) && ( tab.g_res == geom.g_res ) ) ||
+ ( ( geom.s_res != INVALID ) && ( tab.s_res == geom.s_res ) ) )
+ {
+ lprintf("gsc.lookup_geometry: "
+ "geometry lookup found: %ddpi, %ddpl\n",
+ tab.dpi, tab.dpl);
+ return i;
+ }
+ }
+
+ lprintf("gsc.lookup_geometry: "
+ "geometry lookup failed on {%d, %d, 0x%02x, 0x%02x}\n",
+ geom.dpi, geom.dpl, geom.g_res, geom.s_res);
+
+ return INVALID;
+}
+
+/***********************************************************************
+ *
+ * get_geometry -- read geometry from status port
+ *
+ * Returns the index into geometry table or INVALID if it fails to
+ * either read the status byte or lookup the record.
+ */
+
+static int
+get_geometry(const struct gsc_unit *scu)
+{
+ struct gsc_geom geom = NEW_GEOM;
+
+ lprintf("gsc.get_geometry: get geometry at 0x%03x\n", scu->stat);
+
+ if ( ( geom.g_res = inb(scu->stat) ) == FAIL )
+ return INVALID;
+
+ geom.g_res &= GSC_RES_MASK;
+
+ return lookup_geometry(geom, scu);
+}
+
+/***********************************************************************
+ *
+ * buffer_allocate -- allocate/reallocate a buffer
+ */
+
+static int
+buffer_allocate(struct gsc_unit *scu)
+{
+ size_t size;
+
+ size = scu->blen * geomtab[scu->geometry].dpl / 8;
+
+ lprintf("gsc.buffer_allocate: need 0x%x bytes\n", size);
+
+ if ( size > MAX_BUFSIZE )
+ {
+ lprintf("gsc.buffer_allocate: 0x%x bytes are too much\n", size);
+ return ENOMEM;
+ }
+
+ if ( scu->sbuf.base != NULL )
+ if ( scu->sbuf.size == size )
+ {
+ lprintf("gsc.buffer_allocate: keep old buffer\n");
+ return SUCCESS;
+ }
+ else
+ {
+ lprintf("gsc.buffer_allocate: release old buffer\n");
+ free( scu->sbuf.base, M_DEVBUF );
+ }
+
+ scu->sbuf.base = (char *)malloc(size, M_DEVBUF, M_WAITOK);
+
+ if ( scu->sbuf.base == NULL )
+ {
+ lprintf("gsc.buffer_allocate: "
+ "buffer allocatation failed for size = 0x%x\n",
+ scu->sbuf.size);
+ return ENOMEM;
+ }
+
+ scu->sbuf.size = size;
+ scu->sbuf.poi = size;
+
+ lprintf("gsc.buffer_allocate: ok\n");
+
+ return SUCCESS;
+}
+
+/***********************************************************************
+ *
+ * buffer_read -- scan a buffer
+ */
+
+static int
+buffer_read(struct gsc_unit *scu)
+{
+ int stb;
+ int res = SUCCESS;
+ int chan_bit;
+ char *p;
+ int sps;
+ int delay;
+
+ lprintf("gsc.buffer_read: begin\n");
+
+ if (scu->ctrl_byte == INVALID)
+ {
+ lprintf("gsc.buffer_read: invalid ctrl_byte\n");
+ return EIO;
+ }
+
+ sps=splbio();
+
+ outb( scu->ctrl, scu->ctrl_byte | GSC_POWER_ON );
+ outb( scu->clrp, 0 );
+ stb = inb( scu->stat );
+
+ isa_dmastart(B_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
+
+ chan_bit = 0x01 << scu->channel;
+
+ for(delay=0; !(inb(DMA1_READY) & 0x01 << scu->channel); delay += LONG)
+ {
+ if(delay >= scu->btime)
+ {
+ splx(sps);
+ lprintf("gsc.buffer_read: timeout\n");
+ res = EWOULDBLOCK;
+ break;
+ }
+ res = tsleep((caddr_t)scu, GSCPRI | PCATCH, "gscread", LONG);
+ if ( ( res == 0 ) || ( res == EWOULDBLOCK ) )
+ res = SUCCESS;
+ else
+ break;
+ }
+ splx(sps);
+ isa_dmadone(B_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
+ outb( scu->clrp, 0 );
+
+ if(res != SUCCESS)
+ {
+ lprintf("gsc.buffer_read: aborted with %d\n", res);
+ return res;
+ }
+
+ lprintf("gsc.buffer_read: invert buffer\n");
+ for(p = scu->sbuf.base + scu->sbuf.size - 1; p >= scu->sbuf.base; p--)
+ *p = ~*p;
+
+ scu->sbuf.poi = 0;
+ lprintf("gsc.buffer_read: ok\n");
+ return SUCCESS;
+}
+
+/***********************************************************************
+ *
+ * the main functions
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ *
+ * gscprobe
+ *
+ * read status port and check for proper configuration:
+ * - if address group matches (status byte has reasonable value)
+ * - if DMA channel matches (status byte has correct value)
+ */
+
+int
+gscprobe (struct isa_device *isdp)
+{
+ int unit = isdp->id_unit;
+ struct gsc_unit *scu = unittab + unit;
+ int stb;
+ struct gsc_geom geom = NEW_GEOM;
+
+ scu->flags = DEBUG;
+
+ lprintf("gsc%d.probe "
+ "on iobase 0x%03x, irq %d, drq %d, addr %d, size %d\n",
+ unit,
+ isdp->id_iobase,
+ isdp->id_irq,
+ isdp->id_drq,
+ isdp->id_maddr,
+ isdp->id_msize);
+
+ if ( isdp->id_iobase < 0 )
+ {
+ lprintf("gsc%d.probe: no iobase given\n", unit);
+ return PROBE_FAIL;
+ }
+
+ stb = inb( GSC_STAT(isdp->id_iobase) );
+ if (stb == FAIL)
+ {
+ lprintf("gsc%d.probe: get status byte failed\n", unit);
+ return PROBE_FAIL;
+ }
+
+ scu->data = GSC_DATA(isdp->id_iobase);
+ scu->stat = GSC_STAT(isdp->id_iobase);
+ scu->ctrl = GSC_CTRL(isdp->id_iobase);
+ scu->clrp = GSC_CLRP(isdp->id_iobase);
+
+ outb(scu->clrp,stb);
+ stb = inb(scu->stat);
+
+ switch(stb & GSC_CNF_MASK) {
+ case GSC_CNF_DMA1:
+ lprintf("gsc%d.probe: DMA 1\n", unit);
+ scu->channel = 1;
+ break;
+
+ case GSC_CNF_DMA3:
+ lprintf("gsc%d.probe: DMA 3\n", unit);
+ scu->channel = 3;
+ break;
+
+ case GSC_CNF_IRQ3:
+ lprintf("gsc%d.probe: IRQ 3\n", unit);
+ goto probe_noirq;
+ case GSC_CNF_IRQ5:
+ lprintf("gsc%d.probe: IRQ 5\n", unit);
+ probe_noirq:
+ lprintf("gsc%d.probe: sorry, can't use IRQ yet\n", unit);
+ return PROBE_FAIL;
+ default:
+ lprintf("gsc%d.probe: invalid status byte\n", unit, stb);
+ return PROBE_FAIL;
+ }
+
+ geom.g_res = stb & GSC_RES_MASK;
+ scu->geometry = lookup_geometry(geom, scu);
+ if (scu->geometry == INVALID)
+ {
+ lprintf("gsc%d.probe: geometry lookup failed\n", unit);
+ return PROBE_FAIL;
+ }
+ else
+ {
+ scu->ctrl_byte = geomtab[scu->geometry].s_res;
+ outb(scu->ctrl, scu->ctrl_byte | GSC_POWER_ON);
+
+ lprintf("gsc%d.probe: status 0x%02x, %ddpi\n",
+ unit, stb, geomtab[scu->geometry].dpi);
+
+ outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
+ }
+
+ lprintf("gsc%d.probe: ok\n", unit);
+
+ scu->flags &= ~DEBUG;
+
+ return PROBE_SUCCESS;
+}
+
+/***********************************************************************
+ *
+ * gscattach
+ *
+ * finish initialization of unit structure
+ * get geometry value
+ */
+
+int
+gscattach(struct isa_device *isdp)
+{
+ int unit = isdp->id_unit;
+ struct gsc_unit *scu = unittab + unit;
+
+ scu->flags |= DEBUG;
+
+ lprintf("gsc%d.attach: "
+ "iobase 0x%03x, irq %d, drq %d, addr %d, size %d\n",
+ unit,
+ isdp->id_iobase,
+ isdp->id_irq,
+ isdp->id_drq,
+ isdp->id_maddr,
+ isdp->id_msize);
+
+ printf("gsc%d: GeniScan GS-4500 at %ddpi\n",
+ unit, geomtab[scu->geometry].dpi);
+
+ /* initialize buffer structure */
+ scu->sbuf.base = NULL;
+ scu->sbuf.size = INVALID;
+ scu->sbuf.poi = INVALID;
+
+ scu->blen = DEFAULT_BLEN;
+ scu->btime = TIMEOUT;
+
+ scu->flags |= ATTACHED;
+ lprintf("gsc%d.attach: ok\n", unit);
+ scu->flags &= ~DEBUG;
+ return SUCCESS; /* attach must not fail */
+}
+
+/***********************************************************************
+ *
+ * gscopen
+ *
+ * set open flag
+ * set modes according to minor number
+ * don't switch scanner on, wait until first read ioctls go before
+ */
+
+int gscopen (dev_t dev, int flag)
+{
+ int unit = UNIT(minor(dev)) & UNIT_MASK;
+ struct gsc_unit *scu = unittab + unit;
+
+ if ( minor(dev) & DBUG_MASK )
+ scu->flags |= DEBUG;
+ else
+ scu->flags &= ~DEBUG;
+
+ switch(minor(dev) & FRMT_MASK) {
+ case FRMT_PBM:
+ scu->flags |= PBM_MODE;
+ lprintf("gsc%d.open: pbm mode\n", unit);
+ break;
+ case FRMT_RAW:
+ lprintf("gsc%d.open: raw mode\n", unit);
+ scu->flags &= ~PBM_MODE;
+ break;
+ default:
+ lprintf("gsc%d.open: gray maps are not yet supported", unit);
+ return ENXIO;
+ }
+
+ lprintf("gsc%d.open: minor %d\n",
+ unit, minor(dev));
+
+ if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
+ {
+ lprintf("gsc%d.open: unit was not attached successfully 0x04x\n",
+ unit, scu->flags);
+ return ENXIO;
+ }
+
+ if ( scu->flags & OPEN )
+ {
+ lprintf("gsc%d.open: already open", unit);
+ return EBUSY;
+ }
+
+ scu->flags |= OPEN;
+
+ return SUCCESS;
+}
+
+/***********************************************************************
+ *
+ * gscclose
+ *
+ * turn off scanner
+ * release the buffer
+ */
+
+int gscclose (dev_t dev, int flag)
+{
+ int unit = UNIT(minor(dev));
+ struct gsc_unit *scu = unittab + unit;
+
+ lprintf("gsc%d.close: minor %d\n",
+ unit, minor(dev));
+
+ if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
+ {
+ lprintf("gsc%d.read: unit was not attached successfully 0x04x\n",
+ unit, scu->flags);
+ return ENXIO;
+ }
+
+ outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
+
+ if ( scu->sbuf.base != NULL ) free( scu->sbuf.base, M_DEVBUF );
+
+ scu->sbuf.base = NULL;
+ scu->sbuf.size = INVALID;
+ scu->sbuf.poi = INVALID;
+
+ scu->flags &= ~(DEBUG | OPEN | READING);
+
+ return SUCCESS;
+}
+
+/***********************************************************************
+ *
+ * gscread
+ */
+
+int gscread (dev_t dev, struct uio *uio)
+{
+ int unit = UNIT(minor(dev));
+ struct gsc_unit *scu = unittab + unit;
+ size_t nbytes;
+ int res;
+
+ lprintf("gsc%d.read: minor %d\n", unit, minor(dev));
+
+ if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
+ {
+ lprintf("gsc%d.read: unit was not attached successfully 0x04x\n",
+ unit, scu->flags);
+ return ENXIO;
+ }
+
+ if ( !(scu->flags & READING) )
+ {
+ res = buffer_allocate(scu);
+ if ( res == SUCCESS )
+ scu->flags |= READING;
+ else
+ return res;
+
+ scu->ctrl_byte = geomtab[scu->geometry].s_res;
+
+ /* initialize for pbm mode */
+ if ( scu->flags & PBM_MODE )
+ {
+ char *p;
+ int width = geomtab[scu->geometry].dpl;
+
+ sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height);
+ scu->bcount = scu->height * width / 8;
+
+ lprintf("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n",
+ unit, scu->sbuf.base, scu->bcount);
+
+ /* move header to end of sbuf */
+ for(p=scu->sbuf.base; *p; p++);
+ while(--p >= scu->sbuf.base)
+ {
+ *(char *)(scu->sbuf.base + --scu->sbuf.poi) = *p;
+ scu->bcount++;
+ }
+ }
+ }
+
+ lprintf("gsc%d.read(before buffer_read): "
+ "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
+ unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);
+
+ if ( scu->sbuf.poi == scu->sbuf.size )
+ if ( (res = buffer_read(scu)) != SUCCESS )
+ return res;
+
+ lprintf("gsc%d.read(after buffer_read): "
+ "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
+ unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);
+
+ nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi );
+
+ if ( (scu->flags & PBM_MODE) )
+ nbytes = MIN( nbytes, scu->bcount );
+
+ lprintf("gsc%d.read: transferring 0x%x bytes", nbytes);
+
+ res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio);
+ if ( res != SUCCESS )
+ {
+ lprintf("gsc%d.read: uiomove failed %d", unit, res);
+ return res;
+ }
+
+ scu->sbuf.poi += nbytes;
+ if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes;
+
+ lprintf("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
+ unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount);
+
+ return SUCCESS;
+}
+
+/***********************************************************************
+ *
+ * gscioctl
+ *
+ */
+
+int gscioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
+{
+ int unit = UNIT(minor(dev));
+ struct gsc_unit *scu = unittab + unit;
+
+ lprintf("gsc%d.ioctl: minor %d\n",
+ unit, minor(dev));
+
+ if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
+ {
+ lprintf("gsc%d.ioctl: unit was not attached successfully 0x04x\n",
+ unit, scu->flags);
+ return ENXIO;
+ }
+
+ switch(cmd) {
+ case GSC_SRESSW:
+ lprintf("gsc%d.ioctl:GSC_SRESSW\n", unit);
+ if ( scu->flags & READING )
+ {
+ lprintf("gsc%d:ioctl on already reading unit\n", unit);
+ return EBUSY;
+ }
+ scu->geometry = get_geometry(scu);
+ return SUCCESS;
+ case GSC_GRES:
+ *(int *)data=geomtab[scu->geometry].dpi;
+ lprintf("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data);
+ return SUCCESS;
+ case GSC_GWIDTH:
+ *(int *)data=geomtab[scu->geometry].dpl;
+ lprintf("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data);
+ return SUCCESS;
+ case GSC_SRES:
+ case GSC_SWIDTH:
+ lprintf("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n",
+ unit, *(int *)data);
+ { int g;
+ struct gsc_geom geom = NEW_GEOM;
+ if ( cmd == GSC_SRES )
+ geom.dpi = *(int *)data;
+ else
+ geom.dpl = *(int *)data;
+ if ( ( g = lookup_geometry(geom, scu) ) == INVALID )
+ return EINVAL;
+ scu->geometry = g;
+ return SUCCESS;
+ }
+ case GSC_GHEIGHT:
+ *(int *)data=scu->height;
+ lprintf("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data);
+ return SUCCESS;
+ case GSC_SHEIGHT:
+ lprintf("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data);
+ if ( scu->flags & READING )
+ {
+ lprintf("gsc%d:ioctl on already reading unit\n", unit);
+ return EBUSY;
+ }
+ scu->height=*(int *)data;
+ return SUCCESS;
+ case GSC_GBLEN:
+ *(int *)data=scu->blen;
+ lprintf("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data);
+ return SUCCESS;
+ case GSC_SBLEN:
+ lprintf("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data);
+ if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE)
+ {
+ lprintf("gsc%d:ioctl buffer size too high\n", unit);
+ return ENOMEM;
+ }
+ scu->blen=*(int *)data;
+ return SUCCESS;
+ case GSC_GBTIME:
+ *(int *)data = scu->btime / hz;
+ lprintf("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data);
+ return SUCCESS;
+ case GSC_SBTIME:
+ scu->btime = *(int *)data * hz;
+ lprintf("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data);
+ return SUCCESS;
+ default: return ENOTTY;
+ }
+}
+
+#endif /* NGSC > 0 */
diff --git a/sys/i386/isa/gscreg.h b/sys/i386/isa/gscreg.h
new file mode 100644
index 000000000000..f8cafcd1dc48
--- /dev/null
+++ b/sys/i386/isa/gscreg.h
@@ -0,0 +1,87 @@
+/* gscreg.h - port and bit definitions for the Genius GS-4500 interface
+ *
+ *
+ * Copyright (c) 1995 Gunther Schadow. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Gunther Schadow.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without 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.
+ */
+
+/*
+ * status register (r)
+ */
+
+/* the DMA/IRQ jumper configuration */
+
+#define GSC_CNF_MASK 0x5a
+
+#define GSC_CNF_DMA1 (~0x02 & GSC_CNF_MASK)
+#define GSC_CNF_DMA3 (~0x08 & GSC_CNF_MASK)
+#define GSC_CNF_IRQ3 (~0x10 & GSC_CNF_MASK)
+#define GSC_CNF_IRQ5 (~0x40 & GSC_CNF_MASK)
+
+/* the resolution switch setting */
+
+#define GSC_RES_MASK 0x24
+
+#define GSC_RES_400 0x00
+#define GSC_RES_300 0x04
+#define GSC_RES_200 0x20
+#define GSC_RES_100 0x24
+
+/* other flags */
+
+#define GSC_RDY_FLAG 0x80
+
+#define GSC_IRQ_FLAG 0x01
+
+/*
+ * control register (w)
+ */
+
+/* power on */
+
+#define GSC_POWER_ON 0x01
+
+/* pixel per line count */
+
+#define GSC_CNT_MASK 0xf0
+
+#define GSC_CNT_3648 0x30
+#define GSC_CNT_2544 0x90
+#define GSC_CNT_1696 0xb0
+#define GSC_CNT_1648 0xe0
+#define GSC_CNT_1264 0x80
+#define GSC_CNT_840 0xa0
+#define GSC_CNT_424 0xf0
+
+/*
+ * port addresses
+ */
+
+#define GSC_DATA(iob) (iob + (iob == 0x270 ? 0x02 : 0x01))
+#define GSC_STAT(iob) (iob + (iob == 0x270 ? 0x03 : 0x02))
+#define GSC_CTRL(iob) (iob + (iob == 0x270 ? 0x0a : 0x03))
+#define GSC_CLRP(iob) (iob + (iob == 0x270 ? 0x0b : 0x04))
diff --git a/sys/i386/isa/isa.h b/sys/i386/isa/isa.h
index cec13f6b5d97..453b3a5ae4ba 100644
--- a/sys/i386/isa/isa.h
+++ b/sys/i386/isa/isa.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.h 5.7 (Berkeley) 5/9/91
- * $Id: isa.h,v 1.10 1994/11/19 18:47:57 phk Exp $
+ * $Id: isa.h,v 1.11 1994/11/19 18:59:04 phk Exp $
*/
#ifndef _I386_ISA_ISA_H_
@@ -79,12 +79,13 @@
#define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */
#define IO_GAME 0x200 /* Game Controller */
- /* 0x208 - 0x277 Open */
+#define IO_GSC1 0x270 /* -- 0x27B! GeniScan GS-4500 addr.grp. 1 */
+#define IO_GSC2 0x2e0 /* GeniScan GS-4500 addr.grp. 2 */
+#define IO_GSC3 0x370 /* GeniScan GS-4500 addr.grp. 3 */
+#define IO_GSC4 0x3e0 /* GeniScan GS-4500 addr.grp. 4 */
#define IO_LPT2 0x278 /* Parallel Port #2 */
- /* 0x280 - 0x2E7 Open */
-
#define IO_COM4 0x2e8 /* COM4 i/o address */
/* 0x2F0 - 0x2F7 Open */