Merge from vendor branch BIND:
[dragonfly.git] / sys / dev / video / gsc / gsc.c
1 /* gsc.c - device driver for handy scanners
2  *
3  * Current version supports:
4  *
5  *      - Genius GS-4500
6  *
7  * Copyright (c) 1995 Gunther Schadow.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
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.
22  *
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.
33  *
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.9 2004/05/19 22:52:54 dillon Exp $
36  *
37  */
38
39 #include "use_gsc.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/conf.h>
43 #include <sys/buf.h>
44 #include <sys/malloc.h>
45 #include <sys/kernel.h>
46 #include <sys/uio.h>
47
48 #include <machine/gsc.h>
49
50 #include <bus/isa/i386/isa.h>
51 #include <bus/isa/i386/isa_device.h>
52 #include "gscreg.h"
53
54 /***********************************************************************
55  *
56  * CONSTANTS & DEFINES
57  *
58  ***********************************************************************/
59
60 #define PROBE_FAIL    0
61 #define PROBE_SUCCESS IO_GSCSIZE
62 #define ATTACH_FAIL   0
63 #define ATTACH_SUCCESS 1
64 #define SUCCESS       0
65 #define FAIL         -1
66 #define INVALID       FAIL
67
68 #define DMA1_READY  0x08
69
70 #ifdef GSCDEBUG
71 #define lprintf(args)                                           \
72                 do {                                            \
73                         if (scu->flags & FLAG_DEBUG)            \
74                                 printf args;                    \
75                 } while (0)
76 #else
77 #define lprintf(args)
78 #endif
79
80 #define TIMEOUT (hz*15)  /* timeout while reading a buffer - default value */
81 #define LONG    (hz/60)  /* timesteps while reading a buffer */
82
83 /***********************************************************************
84  *
85  * LAYOUT OF THE MINOR NUMBER
86  *
87  ***********************************************************************/
88
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 */
96 #define FRMT_PGM  0x18
97
98 /***********************************************************************
99  *
100  * THE GEMOMETRY TABLE
101  *
102  ***********************************************************************/
103
104 #define GEOMTAB_SIZE 7
105
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},
119 };
120
121 #define NEW_GEOM { INVALID, INVALID, INVALID, INVALID }
122
123 /***********************************************************************
124  *
125  * THE TABLE OF UNITS
126  *
127  ***********************************************************************/
128
129 struct _sbuf {
130   size_t  size;
131   size_t  poi;
132   char   *base;
133 };
134
135 struct gsc_unit {
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 */
141   int flags;
142 #define ATTACHED 0x01
143 #define OPEN     0x02
144 #define READING  0x04
145 #define EOF      0x08
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 */
151   struct  _sbuf sbuf;
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 */
156 };
157
158 static struct gsc_unit unittab[NGSC];
159
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!!!
164  */
165 #define MAX_BUFSIZE 0x3000
166 #define DEFAULT_BLEN 59
167
168 /***********************************************************************
169  *
170  * THE PER-DRIVER RECORD FOR ISA.C
171  *
172  ***********************************************************************/
173
174 static  int gscprobe (struct isa_device *isdp);
175 static  int gscattach(struct isa_device *isdp);
176
177 struct isa_driver gscdriver = { gscprobe, gscattach, "gsc" };
178
179 static  d_open_t        gscopen;
180 static  d_close_t       gscclose;
181 static  d_read_t        gscread;
182 static  d_ioctl_t       gscioctl;
183
184 #define CDEV_MAJOR 47
185 static struct cdevsw gsc_cdevsw = {
186         /* name */      "gsc",
187         /* maj */       CDEV_MAJOR,
188         /* flags */     0,
189         /* port */      NULL,
190         /* clone */     NULL,
191
192         /* open */      gscopen,
193         /* close */     gscclose,
194         /* read */      gscread,
195         /* write */     nowrite,
196         /* ioctl */     gscioctl,
197         /* poll */      nopoll,
198         /* mmap */      nommap,
199         /* strategy */  nostrategy,
200         /* dump */      nodump,
201         /* psize */     nopsize
202 };
203
204
205 /***********************************************************************
206  *
207  * LOCALLY USED SUBROUTINES
208  *
209  ***********************************************************************/
210
211 /***********************************************************************
212  *
213  * lookup_geometry -- lookup a record in the geometry table by pattern
214  *
215  * The caller supplies a geometry record pattern, where INVALID
216  * matches anything. Returns the index in the table or INVALID if
217  * lookup fails.
218  */
219
220 static int
221 lookup_geometry(struct gsc_geom geom, const struct gsc_unit *scu)
222 {
223   struct gsc_geom tab;
224   int i;
225
226   for(i=0; i<GEOMTAB_SIZE; i++)
227     {
228       tab = geomtab[i];
229
230       if ( ( ( geom.dpi   != INVALID ) && ( tab.dpi   == geom.dpi   ) ) ||
231            ( ( geom.dpl   != INVALID ) && ( tab.dpl   == geom.dpl   ) ) ||
232            ( ( geom.g_res != INVALID ) && ( tab.g_res == geom.g_res ) ) ||
233            ( ( geom.s_res != INVALID ) && ( tab.s_res == geom.s_res ) ) )
234         {
235           lprintf(("gsc.lookup_geometry: "
236                  "geometry lookup found: %ddpi, %ddpl\n",
237                  tab.dpi, tab.dpl));
238           return i;
239         }
240     }
241
242   lprintf(("gsc.lookup_geometry: "
243          "geometry lookup failed on {%d, %d, 0x%02x, 0x%02x}\n",
244          geom.dpi, geom.dpl, geom.g_res, geom.s_res));
245
246   return INVALID;
247 }
248
249 /***********************************************************************
250  *
251  * get_geometry -- read geometry from status port
252  *
253  * Returns the index into geometry table or INVALID if it fails to
254  * either read the status byte or lookup the record.
255  */
256
257 static int
258 get_geometry(const struct gsc_unit *scu)
259 {
260   struct gsc_geom geom = NEW_GEOM;
261
262   lprintf(("gsc.get_geometry: get geometry at 0x%03x\n", scu->stat));
263
264   if ( ( geom.g_res = inb(scu->stat) ) == FAIL )
265     return INVALID;
266
267   geom.g_res &= GSC_RES_MASK;
268
269   return lookup_geometry(geom, scu);
270 }
271
272 /***********************************************************************
273  *
274  * buffer_allocate -- allocate/reallocate a buffer
275  * Now just checks that the preallocated buffer is large enough.
276  */
277
278 static int
279 buffer_allocate(struct gsc_unit *scu)
280 {
281   size_t size;
282
283   size = scu->blen * geomtab[scu->geometry].dpl / 8;
284
285   lprintf(("gsc.buffer_allocate: need 0x%x bytes\n", size));
286
287   if ( size > MAX_BUFSIZE )
288     {
289       lprintf(("gsc.buffer_allocate: 0x%x bytes are too much\n", size));
290       return ENOMEM;
291     }
292
293   scu->sbuf.size = size;
294   scu->sbuf.poi  = size;
295
296   lprintf(("gsc.buffer_allocate: ok\n"));
297
298   return SUCCESS;
299 }
300
301 /***********************************************************************
302  *
303  * buffer_read -- scan a buffer
304  */
305
306 static int
307 buffer_read(struct gsc_unit *scu)
308 {
309   int stb;
310   int res = SUCCESS;
311   int chan_bit;
312   char *p;
313   int sps;
314   int delay;
315
316   lprintf(("gsc.buffer_read: begin\n"));
317
318   if (scu->ctrl_byte == INVALID)
319     {
320       lprintf(("gsc.buffer_read: invalid ctrl_byte\n"));
321       return EIO;
322     }
323
324   sps=splbio();
325
326   outb( scu->ctrl, scu->ctrl_byte | GSC_POWER_ON );
327   outb( scu->clrp, 0 );
328   stb = inb( scu->stat );
329
330   isa_dmastart(ISADMA_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
331
332   chan_bit = 0x01 << scu->channel;
333
334   for(delay=0; !(inb(DMA1_READY) & 0x01 << scu->channel); delay += LONG)
335     {
336       if(delay >= scu->btime)
337         {
338           splx(sps);
339           lprintf(("gsc.buffer_read: timeout\n"));
340           res = EWOULDBLOCK;
341           break;
342         }
343       res = tsleep((caddr_t)scu, PCATCH, "gscread", LONG);
344       if ( ( res == 0 ) || ( res == EWOULDBLOCK ) )
345         res = SUCCESS;
346       else
347         break;
348     }
349   splx(sps);
350   isa_dmadone(ISADMA_READ, scu->sbuf.base, scu->sbuf.size, scu->channel);
351   outb( scu->clrp, 0 );
352
353   if(res != SUCCESS)
354     {
355       lprintf(("gsc.buffer_read: aborted with %d\n", res));
356       return res;
357     }
358
359   lprintf(("gsc.buffer_read: invert buffer\n"));
360   for(p = scu->sbuf.base + scu->sbuf.size - 1; p >= scu->sbuf.base; p--)
361     *p = ~*p;
362
363   scu->sbuf.poi = 0;
364   lprintf(("gsc.buffer_read: ok\n"));
365   return SUCCESS;
366 }
367
368 /***********************************************************************
369  *
370  * the main functions
371  *
372  ***********************************************************************/
373
374 /***********************************************************************
375  *
376  * gscprobe
377  *
378  * read status port and check for proper configuration:
379  *  - if address group matches (status byte has reasonable value)
380  *  - if DMA channel matches   (status byte has correct value)
381  */
382
383 static int
384 gscprobe (struct isa_device *isdp)
385 {
386   int unit = isdp->id_unit;
387   struct gsc_unit *scu = unittab + unit;
388   int stb;
389   struct gsc_geom geom = NEW_GEOM;
390
391   scu->flags = FLAG_DEBUG;
392
393   lprintf(("gsc%d.probe "
394          "on iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
395          unit,
396          isdp->id_iobase,
397          isdp->id_irq,
398          isdp->id_drq,
399          isdp->id_maddr,
400          isdp->id_msize));
401
402   if ( isdp->id_iobase < 0 )
403     {
404       lprintf(("gsc%d.probe: no iobase given\n", unit));
405       return PROBE_FAIL;
406     }
407
408   stb = inb( GSC_STAT(isdp->id_iobase) );
409   if (stb == FAIL)
410     {
411       lprintf(("gsc%d.probe: get status byte failed\n", unit));
412       return PROBE_FAIL;
413     }
414
415   scu->data = GSC_DATA(isdp->id_iobase);
416   scu->stat = GSC_STAT(isdp->id_iobase);
417   scu->ctrl = GSC_CTRL(isdp->id_iobase);
418   scu->clrp = GSC_CLRP(isdp->id_iobase);
419
420   outb(scu->clrp,stb);
421   stb = inb(scu->stat);
422
423   switch(stb & GSC_CNF_MASK) {
424   case GSC_CNF_DMA1:
425     lprintf(("gsc%d.probe: DMA 1\n", unit));
426     scu->channel = 1;
427     break;
428
429   case GSC_CNF_DMA3:
430     lprintf(("gsc%d.probe: DMA 3\n", unit));
431     scu->channel = 3;
432     break;
433
434   case GSC_CNF_IRQ3:
435     lprintf(("gsc%d.probe: IRQ 3\n", unit));
436     goto probe_noirq;
437   case GSC_CNF_IRQ5:
438     lprintf(("gsc%d.probe: IRQ 5\n", unit));
439   probe_noirq:
440     lprintf(("gsc%d.probe: sorry, can't use IRQ yet\n", unit));
441     return PROBE_FAIL;
442   default:
443     lprintf(("gsc%d.probe: invalid status byte 0x%02x\n", unit, (u_char) stb));
444     return PROBE_FAIL;
445   }
446
447   if (isdp->id_drq < 0)
448     isdp->id_drq = scu->channel;
449   if (scu->channel != isdp->id_drq)
450     {
451       lprintf(("gsc%d.probe: drq mismatch: config: %d; hardware: %d\n",
452               unit, isdp->id_drq, scu->channel));
453       return PROBE_FAIL;
454     }
455
456   geom.g_res = stb & GSC_RES_MASK;
457   scu->geometry = lookup_geometry(geom, scu);
458   if (scu->geometry == INVALID)
459     {
460       lprintf(("gsc%d.probe: geometry lookup failed\n", unit));
461       return PROBE_FAIL;
462     }
463   else
464     {
465       scu->ctrl_byte = geomtab[scu->geometry].s_res;
466       outb(scu->ctrl, scu->ctrl_byte | GSC_POWER_ON);
467
468       lprintf(("gsc%d.probe: status 0x%02x, %ddpi\n",
469              unit, stb, geomtab[scu->geometry].dpi));
470
471       outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
472     }
473
474   lprintf(("gsc%d.probe: ok\n", unit));
475
476   scu->flags &= ~FLAG_DEBUG;
477
478   return PROBE_SUCCESS;
479 }
480
481 /***********************************************************************
482  *
483  * gscattach
484  *
485  * finish initialization of unit structure
486  * get geometry value
487  */
488
489 static int
490 gscattach(struct isa_device *isdp)
491 {
492   int unit = isdp->id_unit;
493   struct gsc_unit *scu = unittab + unit;
494
495   scu->flags |= FLAG_DEBUG;
496
497   lprintf(("gsc%d.attach: "
498          "iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
499          unit,
500          isdp->id_iobase,
501          isdp->id_irq,
502          isdp->id_drq,
503          isdp->id_maddr,
504          isdp->id_msize));
505
506   printf("gsc%d: GeniScan GS-4500 at %ddpi\n",
507          unit, geomtab[scu->geometry].dpi);
508
509   /*
510    * Initialize buffer structure.
511    * XXX this must be done early to give a good chance of getting a
512    * contiguous buffer.  This wastes memory.
513    */
514   scu->sbuf.base = contigmalloc((unsigned long)MAX_BUFSIZE, M_DEVBUF, M_NOWAIT,
515                                 0ul, 0xfffffful, 1ul, 0x10000ul);
516   if ( scu->sbuf.base == NULL )
517     {
518       lprintf(("gsc%d.attach: buffer allocation failed\n", unit));
519       return ATTACH_FAIL;       /* XXX attach must not fail */
520     }
521   scu->sbuf.size = INVALID;
522   scu->sbuf.poi  = INVALID;
523
524   scu->blen = DEFAULT_BLEN;
525   scu->btime = TIMEOUT;
526
527   scu->flags |= ATTACHED;
528   lprintf(("gsc%d.attach: ok\n", unit));
529   scu->flags &= ~FLAG_DEBUG;
530 #define GSC_UID 0
531 #define GSC_GID 13
532   cdevsw_add(&gsc_cdevsw, 0xc0, unit << 6);
533   make_dev(&gsc_cdevsw, unit<<6, GSC_UID, GSC_GID, 0666, "gsc%d", unit);
534   make_dev(&gsc_cdevsw, ((unit<<6) + FRMT_PBM),
535      GSC_UID,  GSC_GID, 0666, "gsc%dp", unit);
536   make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK),
537      GSC_UID,  GSC_GID, 0666, "gsc%dd", unit);
538   make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK+FRMT_PBM),
539      GSC_UID,  GSC_GID, 0666, "gsc%dpd", unit);
540
541   return ATTACH_SUCCESS;
542 }
543
544 /***********************************************************************
545  *
546  * gscopen
547  *
548  * set open flag
549  * set modes according to minor number
550  * don't switch scanner on, wait until first read ioctls go before
551  */
552
553 static  int
554 gscopen  (dev_t dev, int flags, int fmt, struct thread *td)
555 {
556   struct gsc_unit *scu;
557   int unit;
558
559   unit = UNIT(minor(dev)) & UNIT_MASK;
560   if ( unit >= NGSC )
561     {
562 #ifdef GSCDEBUG
563       /* XXX lprintf isn't valid here since there is no scu. */
564       printf("gsc%d.open: unconfigured unit number (max %d)\n", unit, NGSC);
565 #endif
566       return ENXIO;
567     }
568   scu = unittab + unit;
569   if ( !( scu->flags & ATTACHED ) )
570     {
571       lprintf(("gsc%d.open: unit was not attached successfully 0x%04x\n",
572              unit, scu->flags));
573       return ENXIO;
574     }
575
576   if ( minor(dev) & DBUG_MASK )
577     scu->flags |= FLAG_DEBUG;
578   else
579     scu->flags &= ~FLAG_DEBUG;
580
581   switch(minor(dev) & FRMT_MASK) {
582   case FRMT_PBM:
583     scu->flags |= PBM_MODE;
584     lprintf(("gsc%d.open: pbm mode\n", unit));
585     break;
586   case FRMT_RAW:
587     lprintf(("gsc%d.open: raw mode\n", unit));
588     scu->flags &= ~PBM_MODE;
589     break;
590   default:
591     lprintf(("gsc%d.open: gray maps are not yet supported", unit));
592     return ENXIO;
593   }
594
595   lprintf(("gsc%d.open: minor %d\n",
596          unit, minor(dev)));
597
598   if ( scu->flags & OPEN )
599     {
600       lprintf(("gsc%d.open: already open", unit));
601       return EBUSY;
602     }
603
604   if (isa_dma_acquire(scu->channel))
605       return(EBUSY);
606
607   scu->flags |= OPEN;
608
609   return SUCCESS;
610 }
611
612 /***********************************************************************
613  *
614  * gscclose
615  *
616  * turn off scanner
617  * release the buffer
618  */
619
620 static  int
621 gscclose (dev_t dev, int flags, int fmt, struct thread *td)
622 {
623   int unit = UNIT(minor(dev));
624   struct gsc_unit *scu = unittab + unit;
625
626   lprintf(("gsc%d.close: minor %d\n",
627          unit, minor(dev)));
628
629   if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
630     {
631       lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
632              unit, scu->flags));
633       return ENXIO;
634     }
635
636   outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
637
638   scu->sbuf.size = INVALID;
639   scu->sbuf.poi  = INVALID;
640
641   isa_dma_release(scu->channel);
642
643   scu->flags &= ~(FLAG_DEBUG | OPEN | READING);
644
645   return SUCCESS;
646 }
647
648 /***********************************************************************
649  *
650  * gscread
651  */
652
653 static  int
654 gscread  (dev_t dev, struct uio *uio, int ioflag)
655 {
656   int unit = UNIT(minor(dev));
657   struct gsc_unit *scu = unittab + unit;
658   size_t nbytes;
659   int res;
660
661   lprintf(("gsc%d.read: minor %d\n", unit, minor(dev)));
662
663   if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
664     {
665       lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
666              unit, scu->flags));
667       return ENXIO;
668     }
669
670   if ( !(scu->flags & READING) )
671     {
672       res = buffer_allocate(scu);
673       if ( res == SUCCESS )
674         scu->flags |= READING;
675       else
676         return res;
677
678       scu->ctrl_byte = geomtab[scu->geometry].s_res;
679
680       /* initialize for pbm mode */
681       if ( scu->flags & PBM_MODE )
682         {
683           char *p;
684           int width = geomtab[scu->geometry].dpl;
685
686           sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height);
687           scu->bcount = scu->height * width / 8;
688
689           lprintf(("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n",
690                   unit, scu->sbuf.base, scu->bcount));
691
692           /* move header to end of sbuf */
693           for(p=scu->sbuf.base; *p; p++);
694           while(--p >= scu->sbuf.base)
695             {
696               *(char *)(scu->sbuf.base + --scu->sbuf.poi) = *p;
697               scu->bcount++;
698             }
699         }
700     }
701
702   lprintf(("gsc%d.read(before buffer_read): "
703           "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
704           unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
705
706   if ( scu->sbuf.poi == scu->sbuf.size )
707     if ( (res = buffer_read(scu)) != SUCCESS )
708       return res;
709
710   lprintf(("gsc%d.read(after buffer_read): "
711           "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
712           unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
713
714   nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi );
715
716   if ( (scu->flags & PBM_MODE) )
717     nbytes = MIN( nbytes, scu->bcount );
718
719   lprintf(("gsc%d.read: transferring 0x%x bytes", unit, nbytes));
720
721   res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio);
722   if ( res != SUCCESS )
723     {
724       lprintf(("gsc%d.read: uiomove failed %d", unit, res));
725       return res;
726     }
727
728   scu->sbuf.poi += nbytes;
729   if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes;
730
731   lprintf(("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
732           unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
733
734   return SUCCESS;
735 }
736
737 /***********************************************************************
738  *
739  * gscioctl
740  *
741  */
742
743 static  int
744 gscioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
745 {
746   int unit = UNIT(minor(dev));
747   struct gsc_unit *scu = unittab + unit;
748
749   lprintf(("gsc%d.ioctl: minor %d\n",
750          unit, minor(dev)));
751
752   if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
753     {
754       lprintf(("gsc%d.ioctl: unit was not attached successfully 0x%04x\n",
755              unit, scu->flags));
756       return ENXIO;
757     }
758
759   switch(cmd) {
760   case GSC_SRESSW:
761     lprintf(("gsc%d.ioctl:GSC_SRESSW\n", unit));
762     if ( scu->flags & READING )
763       {
764         lprintf(("gsc%d:ioctl on already reading unit\n", unit));
765         return EBUSY;
766       }
767     scu->geometry = get_geometry(scu);
768     return SUCCESS;
769   case GSC_GRES:
770     *(int *)data=geomtab[scu->geometry].dpi;
771     lprintf(("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data));
772     return SUCCESS;
773   case GSC_GWIDTH:
774     *(int *)data=geomtab[scu->geometry].dpl;
775     lprintf(("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data));
776     return SUCCESS;
777   case GSC_SRES:
778   case GSC_SWIDTH:
779     lprintf(("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n",
780            unit, *(int *)data));
781     { int g;
782       struct gsc_geom geom = NEW_GEOM;
783       if ( cmd == GSC_SRES )
784         geom.dpi = *(int *)data;
785       else
786         geom.dpl = *(int *)data;
787       if ( ( g = lookup_geometry(geom, scu) ) == INVALID )
788         return EINVAL;
789       scu->geometry = g;
790       return SUCCESS;
791     }
792   case GSC_GHEIGHT:
793     *(int *)data=scu->height;
794     lprintf(("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data));
795     return SUCCESS;
796   case GSC_SHEIGHT:
797     lprintf(("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data));
798     if ( scu->flags & READING )
799       {
800         lprintf(("gsc%d:ioctl on already reading unit\n", unit));
801         return EBUSY;
802       }
803     scu->height=*(int *)data;
804     return SUCCESS;
805   case GSC_GBLEN:
806     *(int *)data=scu->blen;
807     lprintf(("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data));
808     return SUCCESS;
809   case GSC_SBLEN:
810     lprintf(("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data));
811     if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE)
812       {
813         lprintf(("gsc%d:ioctl buffer size too high\n", unit));
814         return ENOMEM;
815       }
816     scu->blen=*(int *)data;
817     return SUCCESS;
818   case GSC_GBTIME:
819     *(int *)data = scu->btime / hz;
820     lprintf(("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data));
821     return SUCCESS;
822   case GSC_SBTIME:
823     scu->btime = *(int *)data * hz;
824     lprintf(("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data));
825     return SUCCESS;
826   default: return ENOTTY;
827   }
828 }