1 /* gsc.c - device driver for handy scanners
3 * Current version supports:
7 * Copyright (c) 1995 Gunther Schadow. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Gunther Schadow.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * $FreeBSD: src/sys/i386/isa/gsc.c,v 1.35.2.1 2000/08/08 19:49:53 peter Exp $
35 * $DragonFly: src/sys/dev/video/gsc/gsc.c,v 1.2 2003/06/17 04:28:37 dillon Exp $
40 #include <sys/param.h>
41 #include <sys/systm.h>
44 #include <sys/malloc.h>
45 #include <sys/kernel.h>
48 #include <machine/gsc.h>
50 #include <i386/isa/isa.h>
51 #include <i386/isa/isa_device.h>
52 #include <i386/isa/gscreg.h>
54 /***********************************************************************
58 ***********************************************************************/
61 #define PROBE_SUCCESS IO_GSCSIZE
63 #define ATTACH_SUCCESS 1
68 #define DMA1_READY 0x08
71 #define lprintf(args) \
73 if (scu->flags & FLAG_DEBUG) \
80 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
82 #define TIMEOUT (hz*15) /* timeout while reading a buffer - default value */
83 #define LONG (hz/60) /* timesteps while reading a buffer */
84 #define GSCPRI PRIBIO /* priority while reading a buffer */
86 /***********************************************************************
88 * LAYOUT OF THE MINOR NUMBER
90 ***********************************************************************/
92 #define UNIT_MASK 0xc0 /* unit gsc0 .. gsc3 */
93 #define UNIT(x) (x >> 6)
94 #define DBUG_MASK 0x20
95 #define FRMT_MASK 0x18 /* output format */
96 #define FRMT_RAW 0x00 /* output bits as read from scanner */
97 #define FRMT_GRAY 0x10 /* output graymap (not implemented yet) */
98 #define FRMT_PBM 0x08 /* output pbm format */
101 /***********************************************************************
103 * THE GEMOMETRY TABLE
105 ***********************************************************************/
107 #define GEOMTAB_SIZE 7
109 static const struct gsc_geom {
110 int dpi; /* dots per inch */
111 int dpl; /* dots per line */
112 int g_res; /* get resolution value (status flag) */
113 int s_res; /* set resolution value (control register) */
114 } geomtab[GEOMTAB_SIZE] = {
115 { 100, 424, GSC_RES_100, GSC_CNT_424},
116 { 200, 840, GSC_RES_200, GSC_CNT_840},
117 { 300, 1264, GSC_RES_300, GSC_CNT_1264},
118 { 400, 1648, GSC_RES_400, GSC_CNT_1648},
119 { -1, 1696, -1, GSC_CNT_1696},
120 { -2, 2644, -2, GSC_CNT_2544},
121 { -3, 3648, -3, GSC_CNT_3648},
124 #define NEW_GEOM { INVALID, INVALID, INVALID, INVALID }
126 /***********************************************************************
130 ***********************************************************************/
139 int channel; /* DMA channel */
140 int data; /* - video port */
141 int stat; /* - status port */
142 int ctrl; /* - control port */
143 int clrp; /* - clear port */
145 #define ATTACHED 0x01
149 #define FLAG_DEBUG 0x10
150 #define PBM_MODE 0x20
151 int geometry; /* resolution as geomtab index */
152 int blen; /* length of buffer in lines */
153 int btime; /* timeout of buffer in seconds/hz */
155 char ctrl_byte; /* the byte actually written to ctrl port */
156 int height; /* height, for pnm modes */
157 size_t bcount; /* bytes to read, for pnm modes */
158 struct _sbuf hbuf; /* buffer for pnm header data */
161 static struct gsc_unit unittab[NGSC];
163 /* I could not find a reasonable buffer size limit other than by
164 * experiments. MAXPHYS is obviously too much, while DEV_BSIZE and
165 * PAGE_SIZE are really too small. There must be something wrong
166 * with isa_dmastart/isa_dmarangecheck HELP!!!
168 #define MAX_BUFSIZE 0x3000
169 #define DEFAULT_BLEN 59
171 /***********************************************************************
173 * THE PER-DRIVER RECORD FOR ISA.C
175 ***********************************************************************/
177 static int gscprobe (struct isa_device *isdp);
178 static int gscattach(struct isa_device *isdp);
180 struct isa_driver gscdriver = { gscprobe, gscattach, "gsc" };
182 static d_open_t gscopen;
183 static d_close_t gscclose;
184 static d_read_t gscread;
185 static d_ioctl_t gscioctl;
187 #define CDEV_MAJOR 47
188 static struct cdevsw gsc_cdevsw = {
190 /* close */ gscclose,
193 /* ioctl */ gscioctl,
196 /* strategy */ nostrategy,
198 /* maj */ CDEV_MAJOR,
206 /***********************************************************************
208 * LOCALLY USED SUBROUTINES
210 ***********************************************************************/
212 /***********************************************************************
214 * lookup_geometry -- lookup a record in the geometry table by pattern
216 * The caller supplies a geometry record pattern, where INVALID
217 * matches anything. Returns the index in the table or INVALID if
222 lookup_geometry(struct gsc_geom geom, const struct gsc_unit *scu)
227 for(i=0; i<GEOMTAB_SIZE; i++)
231 if ( ( ( geom.dpi != INVALID ) && ( tab.dpi == geom.dpi ) ) ||
232 ( ( geom.dpl != INVALID ) && ( tab.dpl == geom.dpl ) ) ||
233 ( ( geom.g_res != INVALID ) && ( tab.g_res == geom.g_res ) ) ||
234 ( ( geom.s_res != INVALID ) && ( tab.s_res == geom.s_res ) ) )
236 lprintf(("gsc.lookup_geometry: "
237 "geometry lookup found: %ddpi, %ddpl\n",
243 lprintf(("gsc.lookup_geometry: "
244 "geometry lookup failed on {%d, %d, 0x%02x, 0x%02x}\n",
245 geom.dpi, geom.dpl, geom.g_res, geom.s_res));
250 /***********************************************************************
252 * get_geometry -- read geometry from status port
254 * Returns the index into geometry table or INVALID if it fails to
255 * either read the status byte or lookup the record.
259 get_geometry(const struct gsc_unit *scu)
261 struct gsc_geom geom = NEW_GEOM;
263 lprintf(("gsc.get_geometry: get geometry at 0x%03x\n", scu->stat));
265 if ( ( geom.g_res = inb(scu->stat) ) == FAIL )
268 geom.g_res &= GSC_RES_MASK;
270 return lookup_geometry(geom, scu);
273 /***********************************************************************
275 * buffer_allocate -- allocate/reallocate a buffer
276 * Now just checks that the preallocated buffer is large enough.
280 buffer_allocate(struct gsc_unit *scu)
284 size = scu->blen * geomtab[scu->geometry].dpl / 8;
286 lprintf(("gsc.buffer_allocate: need 0x%x bytes\n", size));
288 if ( size > MAX_BUFSIZE )
290 lprintf(("gsc.buffer_allocate: 0x%x bytes are too much\n", size));
294 scu->sbuf.size = size;
295 scu->sbuf.poi = size;
297 lprintf(("gsc.buffer_allocate: ok\n"));
302 /***********************************************************************
304 * buffer_read -- scan a buffer
308 buffer_read(struct gsc_unit *scu)
317 lprintf(("gsc.buffer_read: begin\n"));
319 if (scu->ctrl_byte == INVALID)
321 lprintf(("gsc.buffer_read: invalid ctrl_byte\n"));
327 outb( scu->ctrl, scu->ctrl_byte | GSC_POWER_ON );
328 outb( scu->clrp, 0 );
329 stb = inb( scu->stat );
331 isa_dmastart(ISADMA_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
333 chan_bit = 0x01 << scu->channel;
335 for(delay=0; !(inb(DMA1_READY) & 0x01 << scu->channel); delay += LONG)
337 if(delay >= scu->btime)
340 lprintf(("gsc.buffer_read: timeout\n"));
344 res = tsleep((caddr_t)scu, GSCPRI | PCATCH, "gscread", LONG);
345 if ( ( res == 0 ) || ( res == EWOULDBLOCK ) )
351 isa_dmadone(ISADMA_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
352 outb( scu->clrp, 0 );
356 lprintf(("gsc.buffer_read: aborted with %d\n", res));
360 lprintf(("gsc.buffer_read: invert buffer\n"));
361 for(p = scu->sbuf.base + scu->sbuf.size - 1; p >= scu->sbuf.base; p--)
365 lprintf(("gsc.buffer_read: ok\n"));
369 /***********************************************************************
373 ***********************************************************************/
375 /***********************************************************************
379 * read status port and check for proper configuration:
380 * - if address group matches (status byte has reasonable value)
381 * - if DMA channel matches (status byte has correct value)
385 gscprobe (struct isa_device *isdp)
387 int unit = isdp->id_unit;
388 struct gsc_unit *scu = unittab + unit;
390 struct gsc_geom geom = NEW_GEOM;
394 cdevsw_add(&gsc_cdevsw);
396 scu->flags = FLAG_DEBUG;
398 lprintf(("gsc%d.probe "
399 "on iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
407 if ( isdp->id_iobase < 0 )
409 lprintf(("gsc%d.probe: no iobase given\n", unit));
413 stb = inb( GSC_STAT(isdp->id_iobase) );
416 lprintf(("gsc%d.probe: get status byte failed\n", unit));
420 scu->data = GSC_DATA(isdp->id_iobase);
421 scu->stat = GSC_STAT(isdp->id_iobase);
422 scu->ctrl = GSC_CTRL(isdp->id_iobase);
423 scu->clrp = GSC_CLRP(isdp->id_iobase);
426 stb = inb(scu->stat);
428 switch(stb & GSC_CNF_MASK) {
430 lprintf(("gsc%d.probe: DMA 1\n", unit));
435 lprintf(("gsc%d.probe: DMA 3\n", unit));
440 lprintf(("gsc%d.probe: IRQ 3\n", unit));
443 lprintf(("gsc%d.probe: IRQ 5\n", unit));
445 lprintf(("gsc%d.probe: sorry, can't use IRQ yet\n", unit));
448 lprintf(("gsc%d.probe: invalid status byte 0x%02x\n", unit, (u_char) stb));
452 if (isdp->id_drq < 0)
453 isdp->id_drq = scu->channel;
454 if (scu->channel != isdp->id_drq)
456 lprintf(("gsc%d.probe: drq mismatch: config: %d; hardware: %d\n",
457 unit, isdp->id_drq, scu->channel));
461 geom.g_res = stb & GSC_RES_MASK;
462 scu->geometry = lookup_geometry(geom, scu);
463 if (scu->geometry == INVALID)
465 lprintf(("gsc%d.probe: geometry lookup failed\n", unit));
470 scu->ctrl_byte = geomtab[scu->geometry].s_res;
471 outb(scu->ctrl, scu->ctrl_byte | GSC_POWER_ON);
473 lprintf(("gsc%d.probe: status 0x%02x, %ddpi\n",
474 unit, stb, geomtab[scu->geometry].dpi));
476 outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
479 lprintf(("gsc%d.probe: ok\n", unit));
481 scu->flags &= ~FLAG_DEBUG;
483 return PROBE_SUCCESS;
486 /***********************************************************************
490 * finish initialization of unit structure
495 gscattach(struct isa_device *isdp)
497 int unit = isdp->id_unit;
498 struct gsc_unit *scu = unittab + unit;
500 scu->flags |= FLAG_DEBUG;
502 lprintf(("gsc%d.attach: "
503 "iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
511 printf("gsc%d: GeniScan GS-4500 at %ddpi\n",
512 unit, geomtab[scu->geometry].dpi);
515 * Initialize buffer structure.
516 * XXX this must be done early to give a good chance of getting a
517 * contiguous buffer. This wastes memory.
519 scu->sbuf.base = contigmalloc((unsigned long)MAX_BUFSIZE, M_DEVBUF, M_NOWAIT,
520 0ul, 0xfffffful, 1ul, 0x10000ul);
521 if ( scu->sbuf.base == NULL )
523 lprintf(("gsc%d.attach: buffer allocation failed\n", unit));
524 return ATTACH_FAIL; /* XXX attach must not fail */
526 scu->sbuf.size = INVALID;
527 scu->sbuf.poi = INVALID;
529 scu->blen = DEFAULT_BLEN;
530 scu->btime = TIMEOUT;
532 scu->flags |= ATTACHED;
533 lprintf(("gsc%d.attach: ok\n", unit));
534 scu->flags &= ~FLAG_DEBUG;
537 make_dev(&gsc_cdevsw, unit<<6, GSC_UID, GSC_GID, 0666, "gsc%d", unit);
538 make_dev(&gsc_cdevsw, ((unit<<6) + FRMT_PBM),
539 GSC_UID, GSC_GID, 0666, "gsc%dp", unit);
540 make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK),
541 GSC_UID, GSC_GID, 0666, "gsc%dd", unit);
542 make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK+FRMT_PBM),
543 GSC_UID, GSC_GID, 0666, "gsc%dpd", unit);
545 return ATTACH_SUCCESS;
548 /***********************************************************************
553 * set modes according to minor number
554 * don't switch scanner on, wait until first read ioctls go before
558 gscopen (dev_t dev, int flags, int fmt, struct proc *p)
560 struct gsc_unit *scu;
563 unit = UNIT(minor(dev)) & UNIT_MASK;
567 /* XXX lprintf isn't valid here since there is no scu. */
568 printf("gsc%d.open: unconfigured unit number (max %d)\n", unit, NGSC);
572 scu = unittab + unit;
573 if ( !( scu->flags & ATTACHED ) )
575 lprintf(("gsc%d.open: unit was not attached successfully 0x%04x\n",
580 if ( minor(dev) & DBUG_MASK )
581 scu->flags |= FLAG_DEBUG;
583 scu->flags &= ~FLAG_DEBUG;
585 switch(minor(dev) & FRMT_MASK) {
587 scu->flags |= PBM_MODE;
588 lprintf(("gsc%d.open: pbm mode\n", unit));
591 lprintf(("gsc%d.open: raw mode\n", unit));
592 scu->flags &= ~PBM_MODE;
595 lprintf(("gsc%d.open: gray maps are not yet supported", unit));
599 lprintf(("gsc%d.open: minor %d\n",
602 if ( scu->flags & OPEN )
604 lprintf(("gsc%d.open: already open", unit));
608 if (isa_dma_acquire(scu->channel))
616 /***********************************************************************
625 gscclose (dev_t dev, int flags, int fmt, struct proc *p)
627 int unit = UNIT(minor(dev));
628 struct gsc_unit *scu = unittab + unit;
630 lprintf(("gsc%d.close: minor %d\n",
633 if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
635 lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
640 outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
642 scu->sbuf.size = INVALID;
643 scu->sbuf.poi = INVALID;
645 isa_dma_release(scu->channel);
647 scu->flags &= ~(FLAG_DEBUG | OPEN | READING);
652 /***********************************************************************
658 gscread (dev_t dev, struct uio *uio, int ioflag)
660 int unit = UNIT(minor(dev));
661 struct gsc_unit *scu = unittab + unit;
665 lprintf(("gsc%d.read: minor %d\n", unit, minor(dev)));
667 if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
669 lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
674 if ( !(scu->flags & READING) )
676 res = buffer_allocate(scu);
677 if ( res == SUCCESS )
678 scu->flags |= READING;
682 scu->ctrl_byte = geomtab[scu->geometry].s_res;
684 /* initialize for pbm mode */
685 if ( scu->flags & PBM_MODE )
688 int width = geomtab[scu->geometry].dpl;
690 sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height);
691 scu->bcount = scu->height * width / 8;
693 lprintf(("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n",
694 unit, scu->sbuf.base, scu->bcount));
696 /* move header to end of sbuf */
697 for(p=scu->sbuf.base; *p; p++);
698 while(--p >= scu->sbuf.base)
700 *(char *)(scu->sbuf.base + --scu->sbuf.poi) = *p;
706 lprintf(("gsc%d.read(before buffer_read): "
707 "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
708 unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
710 if ( scu->sbuf.poi == scu->sbuf.size )
711 if ( (res = buffer_read(scu)) != SUCCESS )
714 lprintf(("gsc%d.read(after buffer_read): "
715 "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
716 unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
718 nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi );
720 if ( (scu->flags & PBM_MODE) )
721 nbytes = MIN( nbytes, scu->bcount );
723 lprintf(("gsc%d.read: transferring 0x%x bytes", unit, nbytes));
725 res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio);
726 if ( res != SUCCESS )
728 lprintf(("gsc%d.read: uiomove failed %d", unit, res));
732 scu->sbuf.poi += nbytes;
733 if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes;
735 lprintf(("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
736 unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
741 /***********************************************************************
748 gscioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
750 int unit = UNIT(minor(dev));
751 struct gsc_unit *scu = unittab + unit;
753 lprintf(("gsc%d.ioctl: minor %d\n",
756 if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
758 lprintf(("gsc%d.ioctl: unit was not attached successfully 0x%04x\n",
765 lprintf(("gsc%d.ioctl:GSC_SRESSW\n", unit));
766 if ( scu->flags & READING )
768 lprintf(("gsc%d:ioctl on already reading unit\n", unit));
771 scu->geometry = get_geometry(scu);
774 *(int *)data=geomtab[scu->geometry].dpi;
775 lprintf(("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data));
778 *(int *)data=geomtab[scu->geometry].dpl;
779 lprintf(("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data));
783 lprintf(("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n",
784 unit, *(int *)data));
786 struct gsc_geom geom = NEW_GEOM;
787 if ( cmd == GSC_SRES )
788 geom.dpi = *(int *)data;
790 geom.dpl = *(int *)data;
791 if ( ( g = lookup_geometry(geom, scu) ) == INVALID )
797 *(int *)data=scu->height;
798 lprintf(("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data));
801 lprintf(("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data));
802 if ( scu->flags & READING )
804 lprintf(("gsc%d:ioctl on already reading unit\n", unit));
807 scu->height=*(int *)data;
810 *(int *)data=scu->blen;
811 lprintf(("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data));
814 lprintf(("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data));
815 if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE)
817 lprintf(("gsc%d:ioctl buffer size too high\n", unit));
820 scu->blen=*(int *)data;
823 *(int *)data = scu->btime / hz;
824 lprintf(("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data));
827 scu->btime = *(int *)data * hz;
828 lprintf(("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data));
830 default: return ENOTTY;