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