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