The gsc driver uses the old COMPAT_ISA api. Retire it so we can
retire the COMPAT_ISA shims. If someone were to redo this driver with the new APIs and test it, it can return.
This commit is contained in:
parent
cfd3634f23
commit
e9dd5834c6
@ -264,7 +264,6 @@ i386/isa/clock.c standard
|
||||
i386/isa/cy.c count cy
|
||||
i386/isa/elink.c optional ep
|
||||
i386/isa/elink.c optional ie
|
||||
i386/isa/gsc.c count gsc
|
||||
i386/isa/if_el.c count el
|
||||
i386/isa/isa.c optional isa
|
||||
i386/isa/isa_compat.c optional isa compat_oldisa \
|
||||
|
@ -621,7 +621,6 @@ options SAFE_RNDTEST # enable rndtest support
|
||||
# pmtimer: Timer device driver for power management events (APM or ACPI)
|
||||
# cy: Cyclades serial driver
|
||||
# digi: Digiboard driver
|
||||
# gsc: Genius GS-4500 hand scanner.
|
||||
# spic: Sony Programmable I/O controller (VAIO notebooks)
|
||||
|
||||
# Notes on APM
|
||||
@ -667,10 +666,6 @@ device digi_EPCX_PCI
|
||||
device digi_Xe
|
||||
device digi_Xem
|
||||
device digi_Xr
|
||||
device gsc 1
|
||||
hint.gsc.0.at="isa"
|
||||
hint.gsc.0.port="0x270"
|
||||
hint.gsc.0.drq="3"
|
||||
device spic
|
||||
hint.spic.0.at="isa"
|
||||
hint.spic.0.port="0x10a0"
|
||||
|
@ -1,53 +0,0 @@
|
||||
/* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_GSC_H_
|
||||
#define _MACHINE_GSC_H_
|
||||
|
||||
#include <sys/ioccom.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 /* !_MACHINE_GSC_H_ */
|
@ -1,827 +0,0 @@
|
||||
/* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "gsc.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/gsc.h>
|
||||
|
||||
#include <i386/isa/isa.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <i386/isa/gscreg.h>
|
||||
|
||||
#ifndef COMPAT_OLDISA
|
||||
#error "The gsc device requires the old isa compatibility shims"
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* CONSTANTS & DEFINES
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#define PROBE_FAIL 0
|
||||
#define PROBE_SUCCESS IO_GSCSIZE
|
||||
#define ATTACH_FAIL 0
|
||||
#define ATTACH_SUCCESS 1
|
||||
#define SUCCESS 0
|
||||
#define FAIL -1
|
||||
#define INVALID FAIL
|
||||
|
||||
#define DMA1_READY 0x08
|
||||
|
||||
#ifdef GSCDEBUG
|
||||
#define lprintf(args) \
|
||||
do { \
|
||||
if (scu->flags & FLAG_DEBUG) \
|
||||
printf args; \
|
||||
} while (0)
|
||||
#else
|
||||
#define lprintf(args)
|
||||
#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
|
||||
|
||||
static 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 FLAG_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 */
|
||||
};
|
||||
|
||||
static struct gsc_unit 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
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
static int gscprobe (struct isa_device *isdp);
|
||||
static int gscattach(struct isa_device *isdp);
|
||||
|
||||
struct isa_driver gscdriver = {
|
||||
INTR_TYPE_TTY,
|
||||
gscprobe,
|
||||
gscattach,
|
||||
"gsc"
|
||||
};
|
||||
COMPAT_ISA_DRIVER(gsc, gscdriver);
|
||||
|
||||
static d_open_t gscopen;
|
||||
static d_close_t gscclose;
|
||||
static d_read_t gscread;
|
||||
static d_ioctl_t gscioctl;
|
||||
|
||||
static struct cdevsw gsc_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_flags = D_NEEDGIANT,
|
||||
.d_open = gscopen,
|
||||
.d_close = gscclose,
|
||||
.d_read = gscread,
|
||||
.d_ioctl = gscioctl,
|
||||
.d_name = "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
|
||||
* Now just checks that the preallocated buffer is large enough.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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(ISADMA_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(ISADMA_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)
|
||||
*/
|
||||
|
||||
static 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 = FLAG_DEBUG;
|
||||
|
||||
lprintf(("gsc%d.probe "
|
||||
"on iobase 0x%03x, irq %d, drq %d, addr %p, 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 0x%02x\n", unit, (u_char) stb));
|
||||
return PROBE_FAIL;
|
||||
}
|
||||
|
||||
if (isdp->id_drq < 0)
|
||||
isdp->id_drq = scu->channel;
|
||||
if (scu->channel != isdp->id_drq)
|
||||
{
|
||||
lprintf(("gsc%d.probe: drq mismatch: config: %d; hardware: %d\n",
|
||||
unit, isdp->id_drq, scu->channel));
|
||||
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 &= ~FLAG_DEBUG;
|
||||
|
||||
return PROBE_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* gscattach
|
||||
*
|
||||
* finish initialization of unit structure
|
||||
* get geometry value
|
||||
*/
|
||||
|
||||
static int
|
||||
gscattach(struct isa_device *isdp)
|
||||
{
|
||||
int unit = isdp->id_unit;
|
||||
struct gsc_unit *scu = unittab + unit;
|
||||
|
||||
scu->flags |= FLAG_DEBUG;
|
||||
|
||||
lprintf(("gsc%d.attach: "
|
||||
"iobase 0x%03x, irq %d, drq %d, addr %p, 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.
|
||||
* XXX this must be done early to give a good chance of getting a
|
||||
* contiguous buffer. This wastes memory.
|
||||
*/
|
||||
scu->sbuf.base = contigmalloc((unsigned long)MAX_BUFSIZE, M_DEVBUF, M_NOWAIT,
|
||||
0ul, 0xfffffful, 1ul, 0x10000ul);
|
||||
if ( scu->sbuf.base == NULL )
|
||||
{
|
||||
lprintf(("gsc%d.attach: buffer allocation failed\n", unit));
|
||||
return ATTACH_FAIL; /* XXX attach must not fail */
|
||||
}
|
||||
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 &= ~FLAG_DEBUG;
|
||||
#define GSC_UID 0
|
||||
#define GSC_GID 13
|
||||
make_dev(&gsc_cdevsw, unit<<6, GSC_UID, GSC_GID, 0666, "gsc%d", unit);
|
||||
make_dev(&gsc_cdevsw, ((unit<<6) + FRMT_PBM),
|
||||
GSC_UID, GSC_GID, 0666, "gsc%dp", unit);
|
||||
make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK),
|
||||
GSC_UID, GSC_GID, 0666, "gsc%dd", unit);
|
||||
make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK+FRMT_PBM),
|
||||
GSC_UID, GSC_GID, 0666, "gsc%dpd", unit);
|
||||
|
||||
return ATTACH_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* gscopen
|
||||
*
|
||||
* set open flag
|
||||
* set modes according to minor number
|
||||
* don't switch scanner on, wait until first read ioctls go before
|
||||
*/
|
||||
|
||||
static int
|
||||
gscopen (dev_t dev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
struct gsc_unit *scu;
|
||||
int unit;
|
||||
|
||||
unit = UNIT(minor(dev)) & UNIT_MASK;
|
||||
if ( unit >= NGSC )
|
||||
{
|
||||
#ifdef GSCDEBUG
|
||||
/* XXX lprintf isn't valid here since there is no scu. */
|
||||
printf("gsc%d.open: unconfigured unit number (max %d)\n", unit, NGSC);
|
||||
#endif
|
||||
return ENXIO;
|
||||
}
|
||||
scu = unittab + unit;
|
||||
if ( !( scu->flags & ATTACHED ) )
|
||||
{
|
||||
lprintf(("gsc%d.open: unit was not attached successfully 0x%04x\n",
|
||||
unit, scu->flags));
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
if ( minor(dev) & DBUG_MASK )
|
||||
scu->flags |= FLAG_DEBUG;
|
||||
else
|
||||
scu->flags &= ~FLAG_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 ( scu->flags & OPEN )
|
||||
{
|
||||
lprintf(("gsc%d.open: already open", unit));
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
if (isa_dma_acquire(scu->channel))
|
||||
return(EBUSY);
|
||||
|
||||
scu->flags |= OPEN;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* gscclose
|
||||
*
|
||||
* turn off scanner
|
||||
* release the buffer
|
||||
*/
|
||||
|
||||
static int
|
||||
gscclose (dev_t dev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
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 0x%04x\n",
|
||||
unit, scu->flags));
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
|
||||
|
||||
scu->sbuf.size = INVALID;
|
||||
scu->sbuf.poi = INVALID;
|
||||
|
||||
isa_dma_release(scu->channel);
|
||||
|
||||
scu->flags &= ~(FLAG_DEBUG | OPEN | READING);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* gscread
|
||||
*/
|
||||
|
||||
static int
|
||||
gscread (dev_t dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
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 0x%04x\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", unit, 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
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
gscioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
{
|
||||
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 0x%04x\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;
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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))
|
Loading…
x
Reference in New Issue
Block a user