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