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.
37 #include <sys/param.h>
38 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/kernel.h>
45 #include <machine/gsc.h>
47 #include <i386/isa/isa.h>
48 #include <i386/isa/isa_device.h>
49 #include <i386/isa/gscreg.h>
51 /***********************************************************************
55 ***********************************************************************/
58 #define PROBE_SUCCESS IO_GSCSIZE
60 #define ATTACH_SUCCESS 1
65 #define DMA1_READY 0x08
68 #define lprintf(args) \
70 if (scu->flags & FLAG_DEBUG) \
77 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
79 #define TIMEOUT (hz*15) /* timeout while reading a buffer - default value */
80 #define LONG (hz/60) /* timesteps while reading a buffer */
81 #define GSCPRI PRIBIO /* priority while reading a buffer */
83 /***********************************************************************
85 * LAYOUT OF THE MINOR NUMBER
87 ***********************************************************************/
89 #define UNIT_MASK 0xc0 /* unit gsc0 .. gsc3 */
90 #define UNIT(x) (x >> 6)
91 #define DBUG_MASK 0x20
92 #define FRMT_MASK 0x18 /* output format */
93 #define FRMT_RAW 0x00 /* output bits as read from scanner */
94 #define FRMT_GRAY 0x10 /* output graymap (not implemented yet) */
95 #define FRMT_PBM 0x08 /* output pbm format */
98 /***********************************************************************
100 * THE GEMOMETRY TABLE
102 ***********************************************************************/
104 #define GEOMTAB_SIZE 7
106 static const struct gsc_geom {
107 int dpi; /* dots per inch */
108 int dpl; /* dots per line */
109 int g_res; /* get resolution value (status flag) */
110 int s_res; /* set resolution value (control register) */
111 } geomtab[GEOMTAB_SIZE] = {
112 { 100, 424, GSC_RES_100, GSC_CNT_424},
113 { 200, 840, GSC_RES_200, GSC_CNT_840},
114 { 300, 1264, GSC_RES_300, GSC_CNT_1264},
115 { 400, 1648, GSC_RES_400, GSC_CNT_1648},
116 { -1, 1696, -1, GSC_CNT_1696},
117 { -2, 2644, -2, GSC_CNT_2544},
118 { -3, 3648, -3, GSC_CNT_3648},
121 #define NEW_GEOM { INVALID, INVALID, INVALID, INVALID }
123 /***********************************************************************
127 ***********************************************************************/
136 int channel; /* DMA channel */
137 int data; /* - video port */
138 int stat; /* - status port */
139 int ctrl; /* - control port */
140 int clrp; /* - clear port */
142 #define ATTACHED 0x01
146 #define FLAG_DEBUG 0x10
147 #define PBM_MODE 0x20
148 int geometry; /* resolution as geomtab index */
149 int blen; /* length of buffer in lines */
150 int btime; /* timeout of buffer in seconds/hz */
152 char ctrl_byte; /* the byte actually written to ctrl port */
153 int height; /* height, for pnm modes */
154 size_t bcount; /* bytes to read, for pnm modes */
155 struct _sbuf hbuf; /* buffer for pnm header data */
158 static struct gsc_unit unittab[NGSC];
160 /* I could not find a reasonable buffer size limit other than by
161 * experiments. MAXPHYS is obviously too much, while DEV_BSIZE and
162 * PAGE_SIZE are really too small. There must be something wrong
163 * with isa_dmastart/isa_dmarangecheck HELP!!!
165 #define MAX_BUFSIZE 0x3000
166 #define DEFAULT_BLEN 59
168 /***********************************************************************
170 * THE PER-DRIVER RECORD FOR ISA.C
172 ***********************************************************************/
174 static int gscprobe (struct isa_device *isdp);
175 static int gscattach(struct isa_device *isdp);
177 struct isa_driver gscdriver = { gscprobe, gscattach, "gsc" };
179 static d_open_t gscopen;
180 static d_close_t gscclose;
181 static d_read_t gscread;
182 static d_ioctl_t gscioctl;
184 #define CDEV_MAJOR 47
185 static struct cdevsw gsc_cdevsw = {
187 /* close */ gscclose,
190 /* ioctl */ gscioctl,
193 /* devtotty */ nodevtotty,
196 /* strategy */ nostrategy,
199 /* maj */ CDEV_MAJOR,
208 /***********************************************************************
210 * LOCALLY USED SUBROUTINES
212 ***********************************************************************/
214 /***********************************************************************
216 * lookup_geometry -- lookup a record in the geometry table by pattern
218 * The caller supplies a geometry record pattern, where INVALID
219 * matches anything. Returns the index in the table or INVALID if
224 lookup_geometry(struct gsc_geom geom, const struct gsc_unit *scu)
229 for(i=0; i<GEOMTAB_SIZE; i++)
233 if ( ( ( geom.dpi != INVALID ) && ( tab.dpi == geom.dpi ) ) ||
234 ( ( geom.dpl != INVALID ) && ( tab.dpl == geom.dpl ) ) ||
235 ( ( geom.g_res != INVALID ) && ( tab.g_res == geom.g_res ) ) ||
236 ( ( geom.s_res != INVALID ) && ( tab.s_res == geom.s_res ) ) )
238 lprintf(("gsc.lookup_geometry: "
239 "geometry lookup found: %ddpi, %ddpl\n",
245 lprintf(("gsc.lookup_geometry: "
246 "geometry lookup failed on {%d, %d, 0x%02x, 0x%02x}\n",
247 geom.dpi, geom.dpl, geom.g_res, geom.s_res));
252 /***********************************************************************
254 * get_geometry -- read geometry from status port
256 * Returns the index into geometry table or INVALID if it fails to
257 * either read the status byte or lookup the record.
261 get_geometry(const struct gsc_unit *scu)
263 struct gsc_geom geom = NEW_GEOM;
265 lprintf(("gsc.get_geometry: get geometry at 0x%03x\n", scu->stat));
267 if ( ( geom.g_res = inb(scu->stat) ) == FAIL )
270 geom.g_res &= GSC_RES_MASK;
272 return lookup_geometry(geom, scu);
275 /***********************************************************************
277 * buffer_allocate -- allocate/reallocate a buffer
278 * Now just checks that the preallocated buffer is large enough.
282 buffer_allocate(struct gsc_unit *scu)
286 size = scu->blen * geomtab[scu->geometry].dpl / 8;
288 lprintf(("gsc.buffer_allocate: need 0x%x bytes\n", size));
290 if ( size > MAX_BUFSIZE )
292 lprintf(("gsc.buffer_allocate: 0x%x bytes are too much\n", size));
296 scu->sbuf.size = size;
297 scu->sbuf.poi = size;
299 lprintf(("gsc.buffer_allocate: ok\n"));
304 /***********************************************************************
306 * buffer_read -- scan a buffer
310 buffer_read(struct gsc_unit *scu)
319 lprintf(("gsc.buffer_read: begin\n"));
321 if (scu->ctrl_byte == INVALID)
323 lprintf(("gsc.buffer_read: invalid ctrl_byte\n"));
329 outb( scu->ctrl, scu->ctrl_byte | GSC_POWER_ON );
330 outb( scu->clrp, 0 );
331 stb = inb( scu->stat );
333 isa_dmastart(B_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
335 chan_bit = 0x01 << scu->channel;
337 for(delay=0; !(inb(DMA1_READY) & 0x01 << scu->channel); delay += LONG)
339 if(delay >= scu->btime)
342 lprintf(("gsc.buffer_read: timeout\n"));
346 res = tsleep((caddr_t)scu, GSCPRI | PCATCH, "gscread", LONG);
347 if ( ( res == 0 ) || ( res == EWOULDBLOCK ) )
353 isa_dmadone(B_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
354 outb( scu->clrp, 0 );
358 lprintf(("gsc.buffer_read: aborted with %d\n", res));
362 lprintf(("gsc.buffer_read: invert buffer\n"));
363 for(p = scu->sbuf.base + scu->sbuf.size - 1; p >= scu->sbuf.base; p--)
367 lprintf(("gsc.buffer_read: ok\n"));
371 /***********************************************************************
375 ***********************************************************************/
377 /***********************************************************************
381 * read status port and check for proper configuration:
382 * - if address group matches (status byte has reasonable value)
383 * - if DMA channel matches (status byte has correct value)
387 gscprobe (struct isa_device *isdp)
389 int unit = isdp->id_unit;
390 struct gsc_unit *scu = unittab + unit;
392 struct gsc_geom geom = NEW_GEOM;
396 cdevsw_add(&gsc_cdevsw);
398 scu->flags = FLAG_DEBUG;
400 lprintf(("gsc%d.probe "
401 "on iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
409 if ( isdp->id_iobase < 0 )
411 lprintf(("gsc%d.probe: no iobase given\n", unit));
415 stb = inb( GSC_STAT(isdp->id_iobase) );
418 lprintf(("gsc%d.probe: get status byte failed\n", unit));
422 scu->data = GSC_DATA(isdp->id_iobase);
423 scu->stat = GSC_STAT(isdp->id_iobase);
424 scu->ctrl = GSC_CTRL(isdp->id_iobase);
425 scu->clrp = GSC_CLRP(isdp->id_iobase);
428 stb = inb(scu->stat);
430 switch(stb & GSC_CNF_MASK) {
432 lprintf(("gsc%d.probe: DMA 1\n", unit));
437 lprintf(("gsc%d.probe: DMA 3\n", unit));
442 lprintf(("gsc%d.probe: IRQ 3\n", unit));
445 lprintf(("gsc%d.probe: IRQ 5\n", unit));
447 lprintf(("gsc%d.probe: sorry, can't use IRQ yet\n", unit));
450 lprintf(("gsc%d.probe: invalid status byte 0x%02x\n", unit, (u_char) stb));
454 if (isdp->id_drq < 0)
455 isdp->id_drq = scu->channel;
456 if (scu->channel != isdp->id_drq)
458 lprintf(("gsc%d.probe: drq mismatch: config: %d; hardware: %d\n",
459 unit, isdp->id_drq, scu->channel));
463 geom.g_res = stb & GSC_RES_MASK;
464 scu->geometry = lookup_geometry(geom, scu);
465 if (scu->geometry == INVALID)
467 lprintf(("gsc%d.probe: geometry lookup failed\n", unit));
472 scu->ctrl_byte = geomtab[scu->geometry].s_res;
473 outb(scu->ctrl, scu->ctrl_byte | GSC_POWER_ON);
475 lprintf(("gsc%d.probe: status 0x%02x, %ddpi\n",
476 unit, stb, geomtab[scu->geometry].dpi));
478 outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
481 lprintf(("gsc%d.probe: ok\n", unit));
483 scu->flags &= ~FLAG_DEBUG;
485 return PROBE_SUCCESS;
488 /***********************************************************************
492 * finish initialization of unit structure
497 gscattach(struct isa_device *isdp)
499 int unit = isdp->id_unit;
500 struct gsc_unit *scu = unittab + unit;
502 scu->flags |= FLAG_DEBUG;
504 lprintf(("gsc%d.attach: "
505 "iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
513 printf("gsc%d: GeniScan GS-4500 at %ddpi\n",
514 unit, geomtab[scu->geometry].dpi);
517 * Initialize buffer structure.
518 * XXX this must be done early to give a good chance of getting a
519 * contiguous buffer. This wastes memory.
521 scu->sbuf.base = contigmalloc((unsigned long)MAX_BUFSIZE, M_DEVBUF, M_NOWAIT,
522 0ul, 0xfffffful, 1ul, 0x10000ul);
523 if ( scu->sbuf.base == NULL )
525 lprintf(("gsc%d.attach: buffer allocation failed\n", unit));
526 return ATTACH_FAIL; /* XXX attach must not fail */
528 scu->sbuf.size = INVALID;
529 scu->sbuf.poi = INVALID;
531 scu->blen = DEFAULT_BLEN;
532 scu->btime = TIMEOUT;
534 scu->flags |= ATTACHED;
535 lprintf(("gsc%d.attach: ok\n", unit));
536 scu->flags &= ~FLAG_DEBUG;
539 make_dev(&gsc_cdevsw, unit<<6, GSC_UID, GSC_GID, 0666, "gsc%d", unit);
540 make_dev(&gsc_cdevsw, ((unit<<6) + FRMT_PBM),
541 GSC_UID, GSC_GID, 0666, "gsc%dp", unit);
542 make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK),
543 GSC_UID, GSC_GID, 0666, "gsc%dd", unit);
544 make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK+FRMT_PBM),
545 GSC_UID, GSC_GID, 0666, "gsc%dpd", unit);
547 return ATTACH_SUCCESS;
550 /***********************************************************************
555 * set modes according to minor number
556 * don't switch scanner on, wait until first read ioctls go before
560 gscopen (dev_t dev, int flags, int fmt, struct proc *p)
562 struct gsc_unit *scu;
565 unit = UNIT(minor(dev)) & UNIT_MASK;
569 /* XXX lprintf isn't valid here since there is no scu. */
570 printf("gsc%d.open: unconfigured unit number (max %d)\n", unit, NGSC);
574 scu = unittab + unit;
575 if ( !( scu->flags & ATTACHED ) )
577 lprintf(("gsc%d.open: unit was not attached successfully 0x%04x\n",
582 if ( minor(dev) & DBUG_MASK )
583 scu->flags |= FLAG_DEBUG;
585 scu->flags &= ~FLAG_DEBUG;
587 switch(minor(dev) & FRMT_MASK) {
589 scu->flags |= PBM_MODE;
590 lprintf(("gsc%d.open: pbm mode\n", unit));
593 lprintf(("gsc%d.open: raw mode\n", unit));
594 scu->flags &= ~PBM_MODE;
597 lprintf(("gsc%d.open: gray maps are not yet supported", unit));
601 lprintf(("gsc%d.open: minor %d\n",
604 if ( scu->flags & OPEN )
606 lprintf(("gsc%d.open: already open", unit));
610 if (isa_dma_acquire(scu->channel))
618 /***********************************************************************
627 gscclose (dev_t dev, int flags, int fmt, struct proc *p)
629 int unit = UNIT(minor(dev));
630 struct gsc_unit *scu = unittab + unit;
632 lprintf(("gsc%d.close: minor %d\n",
635 if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
637 lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
642 outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
644 scu->sbuf.size = INVALID;
645 scu->sbuf.poi = INVALID;
647 isa_dma_release(scu->channel);
649 scu->flags &= ~(FLAG_DEBUG | OPEN | READING);
654 /***********************************************************************
660 gscread (dev_t dev, struct uio *uio, int ioflag)
662 int unit = UNIT(minor(dev));
663 struct gsc_unit *scu = unittab + unit;
667 lprintf(("gsc%d.read: minor %d\n", unit, minor(dev)));
669 if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
671 lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
676 if ( !(scu->flags & READING) )
678 res = buffer_allocate(scu);
679 if ( res == SUCCESS )
680 scu->flags |= READING;
684 scu->ctrl_byte = geomtab[scu->geometry].s_res;
686 /* initialize for pbm mode */
687 if ( scu->flags & PBM_MODE )
690 int width = geomtab[scu->geometry].dpl;
692 sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height);
693 scu->bcount = scu->height * width / 8;
695 lprintf(("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n",
696 unit, scu->sbuf.base, scu->bcount));
698 /* move header to end of sbuf */
699 for(p=scu->sbuf.base; *p; p++);
700 while(--p >= scu->sbuf.base)
702 *(char *)(scu->sbuf.base + --scu->sbuf.poi) = *p;
708 lprintf(("gsc%d.read(before buffer_read): "
709 "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
710 unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
712 if ( scu->sbuf.poi == scu->sbuf.size )
713 if ( (res = buffer_read(scu)) != SUCCESS )
716 lprintf(("gsc%d.read(after buffer_read): "
717 "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
718 unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
720 nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi );
722 if ( (scu->flags & PBM_MODE) )
723 nbytes = MIN( nbytes, scu->bcount );
725 lprintf(("gsc%d.read: transferring 0x%x bytes", unit, nbytes));
727 res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio);
728 if ( res != SUCCESS )
730 lprintf(("gsc%d.read: uiomove failed %d", unit, res));
734 scu->sbuf.poi += nbytes;
735 if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes;
737 lprintf(("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
738 unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
743 /***********************************************************************
750 gscioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
752 int unit = UNIT(minor(dev));
753 struct gsc_unit *scu = unittab + unit;
755 lprintf(("gsc%d.ioctl: minor %d\n",
758 if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
760 lprintf(("gsc%d.ioctl: unit was not attached successfully 0x%04x\n",
767 lprintf(("gsc%d.ioctl:GSC_SRESSW\n", unit));
768 if ( scu->flags & READING )
770 lprintf(("gsc%d:ioctl on already reading unit\n", unit));
773 scu->geometry = get_geometry(scu);
776 *(int *)data=geomtab[scu->geometry].dpi;
777 lprintf(("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data));
780 *(int *)data=geomtab[scu->geometry].dpl;
781 lprintf(("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data));
785 lprintf(("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n",
786 unit, *(int *)data));
788 struct gsc_geom geom = NEW_GEOM;
789 if ( cmd == GSC_SRES )
790 geom.dpi = *(int *)data;
792 geom.dpl = *(int *)data;
793 if ( ( g = lookup_geometry(geom, scu) ) == INVALID )
799 *(int *)data=scu->height;
800 lprintf(("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data));
803 lprintf(("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data));
804 if ( scu->flags & READING )
806 lprintf(("gsc%d:ioctl on already reading unit\n", unit));
809 scu->height=*(int *)data;
812 *(int *)data=scu->blen;
813 lprintf(("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data));
816 lprintf(("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data));
817 if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE)
819 lprintf(("gsc%d:ioctl buffer size too high\n", unit));
822 scu->blen=*(int *)data;
825 *(int *)data = scu->btime / hz;
826 lprintf(("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data));
829 scu->btime = *(int *)data * hz;
830 lprintf(("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data));
832 default: return ENOTTY;
836 #endif /* NGSC > 0 */