device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).
[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.8 2004/05/13 23:49:22 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   static int once;
391
392   if (!once++)
393         cdevsw_add(&gsc_cdevsw);
394
395   scu->flags = FLAG_DEBUG;
396
397   lprintf(("gsc%d.probe "
398          "on iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
399          unit,
400          isdp->id_iobase,
401          isdp->id_irq,
402          isdp->id_drq,
403          isdp->id_maddr,
404          isdp->id_msize));
405
406   if ( isdp->id_iobase < 0 )
407     {
408       lprintf(("gsc%d.probe: no iobase given\n", unit));
409       return PROBE_FAIL;
410     }
411
412   stb = inb( GSC_STAT(isdp->id_iobase) );
413   if (stb == FAIL)
414     {
415       lprintf(("gsc%d.probe: get status byte failed\n", unit));
416       return PROBE_FAIL;
417     }
418
419   scu->data = GSC_DATA(isdp->id_iobase);
420   scu->stat = GSC_STAT(isdp->id_iobase);
421   scu->ctrl = GSC_CTRL(isdp->id_iobase);
422   scu->clrp = GSC_CLRP(isdp->id_iobase);
423
424   outb(scu->clrp,stb);
425   stb = inb(scu->stat);
426
427   switch(stb & GSC_CNF_MASK) {
428   case GSC_CNF_DMA1:
429     lprintf(("gsc%d.probe: DMA 1\n", unit));
430     scu->channel = 1;
431     break;
432
433   case GSC_CNF_DMA3:
434     lprintf(("gsc%d.probe: DMA 3\n", unit));
435     scu->channel = 3;
436     break;
437
438   case GSC_CNF_IRQ3:
439     lprintf(("gsc%d.probe: IRQ 3\n", unit));
440     goto probe_noirq;
441   case GSC_CNF_IRQ5:
442     lprintf(("gsc%d.probe: IRQ 5\n", unit));
443   probe_noirq:
444     lprintf(("gsc%d.probe: sorry, can't use IRQ yet\n", unit));
445     return PROBE_FAIL;
446   default:
447     lprintf(("gsc%d.probe: invalid status byte 0x%02x\n", unit, (u_char) stb));
448     return PROBE_FAIL;
449   }
450
451   if (isdp->id_drq < 0)
452     isdp->id_drq = scu->channel;
453   if (scu->channel != isdp->id_drq)
454     {
455       lprintf(("gsc%d.probe: drq mismatch: config: %d; hardware: %d\n",
456               unit, isdp->id_drq, scu->channel));
457       return PROBE_FAIL;
458     }
459
460   geom.g_res = stb & GSC_RES_MASK;
461   scu->geometry = lookup_geometry(geom, scu);
462   if (scu->geometry == INVALID)
463     {
464       lprintf(("gsc%d.probe: geometry lookup failed\n", unit));
465       return PROBE_FAIL;
466     }
467   else
468     {
469       scu->ctrl_byte = geomtab[scu->geometry].s_res;
470       outb(scu->ctrl, scu->ctrl_byte | GSC_POWER_ON);
471
472       lprintf(("gsc%d.probe: status 0x%02x, %ddpi\n",
473              unit, stb, geomtab[scu->geometry].dpi));
474
475       outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
476     }
477
478   lprintf(("gsc%d.probe: ok\n", unit));
479
480   scu->flags &= ~FLAG_DEBUG;
481
482   return PROBE_SUCCESS;
483 }
484
485 /***********************************************************************
486  *
487  * gscattach
488  *
489  * finish initialization of unit structure
490  * get geometry value
491  */
492
493 static int
494 gscattach(struct isa_device *isdp)
495 {
496   int unit = isdp->id_unit;
497   struct gsc_unit *scu = unittab + unit;
498
499   scu->flags |= FLAG_DEBUG;
500
501   lprintf(("gsc%d.attach: "
502          "iobase 0x%03x, irq %d, drq %d, addr %p, size %d\n",
503          unit,
504          isdp->id_iobase,
505          isdp->id_irq,
506          isdp->id_drq,
507          isdp->id_maddr,
508          isdp->id_msize));
509
510   printf("gsc%d: GeniScan GS-4500 at %ddpi\n",
511          unit, geomtab[scu->geometry].dpi);
512
513   /*
514    * Initialize buffer structure.
515    * XXX this must be done early to give a good chance of getting a
516    * contiguous buffer.  This wastes memory.
517    */
518   scu->sbuf.base = contigmalloc((unsigned long)MAX_BUFSIZE, M_DEVBUF, M_NOWAIT,
519                                 0ul, 0xfffffful, 1ul, 0x10000ul);
520   if ( scu->sbuf.base == NULL )
521     {
522       lprintf(("gsc%d.attach: buffer allocation failed\n", unit));
523       return ATTACH_FAIL;       /* XXX attach must not fail */
524     }
525   scu->sbuf.size = INVALID;
526   scu->sbuf.poi  = INVALID;
527
528   scu->blen = DEFAULT_BLEN;
529   scu->btime = TIMEOUT;
530
531   scu->flags |= ATTACHED;
532   lprintf(("gsc%d.attach: ok\n", unit));
533   scu->flags &= ~FLAG_DEBUG;
534 #define GSC_UID 0
535 #define GSC_GID 13
536   make_dev(&gsc_cdevsw, unit<<6, GSC_UID, GSC_GID, 0666, "gsc%d", unit);
537   make_dev(&gsc_cdevsw, ((unit<<6) + FRMT_PBM),
538      GSC_UID,  GSC_GID, 0666, "gsc%dp", unit);
539   make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK),
540      GSC_UID,  GSC_GID, 0666, "gsc%dd", unit);
541   make_dev(&gsc_cdevsw, ((unit<<6) + DBUG_MASK+FRMT_PBM),
542      GSC_UID,  GSC_GID, 0666, "gsc%dpd", unit);
543
544   return ATTACH_SUCCESS;
545 }
546
547 /***********************************************************************
548  *
549  * gscopen
550  *
551  * set open flag
552  * set modes according to minor number
553  * don't switch scanner on, wait until first read ioctls go before
554  */
555
556 static  int
557 gscopen  (dev_t dev, int flags, int fmt, struct thread *td)
558 {
559   struct gsc_unit *scu;
560   int unit;
561
562   unit = UNIT(minor(dev)) & UNIT_MASK;
563   if ( unit >= NGSC )
564     {
565 #ifdef GSCDEBUG
566       /* XXX lprintf isn't valid here since there is no scu. */
567       printf("gsc%d.open: unconfigured unit number (max %d)\n", unit, NGSC);
568 #endif
569       return ENXIO;
570     }
571   scu = unittab + unit;
572   if ( !( scu->flags & ATTACHED ) )
573     {
574       lprintf(("gsc%d.open: unit was not attached successfully 0x%04x\n",
575              unit, scu->flags));
576       return ENXIO;
577     }
578
579   if ( minor(dev) & DBUG_MASK )
580     scu->flags |= FLAG_DEBUG;
581   else
582     scu->flags &= ~FLAG_DEBUG;
583
584   switch(minor(dev) & FRMT_MASK) {
585   case FRMT_PBM:
586     scu->flags |= PBM_MODE;
587     lprintf(("gsc%d.open: pbm mode\n", unit));
588     break;
589   case FRMT_RAW:
590     lprintf(("gsc%d.open: raw mode\n", unit));
591     scu->flags &= ~PBM_MODE;
592     break;
593   default:
594     lprintf(("gsc%d.open: gray maps are not yet supported", unit));
595     return ENXIO;
596   }
597
598   lprintf(("gsc%d.open: minor %d\n",
599          unit, minor(dev)));
600
601   if ( scu->flags & OPEN )
602     {
603       lprintf(("gsc%d.open: already open", unit));
604       return EBUSY;
605     }
606
607   if (isa_dma_acquire(scu->channel))
608       return(EBUSY);
609
610   scu->flags |= OPEN;
611
612   return SUCCESS;
613 }
614
615 /***********************************************************************
616  *
617  * gscclose
618  *
619  * turn off scanner
620  * release the buffer
621  */
622
623 static  int
624 gscclose (dev_t dev, int flags, int fmt, struct thread *td)
625 {
626   int unit = UNIT(minor(dev));
627   struct gsc_unit *scu = unittab + unit;
628
629   lprintf(("gsc%d.close: minor %d\n",
630          unit, minor(dev)));
631
632   if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
633     {
634       lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
635              unit, scu->flags));
636       return ENXIO;
637     }
638
639   outb(scu->ctrl, scu->ctrl_byte & ~GSC_POWER_ON);
640
641   scu->sbuf.size = INVALID;
642   scu->sbuf.poi  = INVALID;
643
644   isa_dma_release(scu->channel);
645
646   scu->flags &= ~(FLAG_DEBUG | OPEN | READING);
647
648   return SUCCESS;
649 }
650
651 /***********************************************************************
652  *
653  * gscread
654  */
655
656 static  int
657 gscread  (dev_t dev, struct uio *uio, int ioflag)
658 {
659   int unit = UNIT(minor(dev));
660   struct gsc_unit *scu = unittab + unit;
661   size_t nbytes;
662   int res;
663
664   lprintf(("gsc%d.read: minor %d\n", unit, minor(dev)));
665
666   if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
667     {
668       lprintf(("gsc%d.read: unit was not attached successfully 0x%04x\n",
669              unit, scu->flags));
670       return ENXIO;
671     }
672
673   if ( !(scu->flags & READING) )
674     {
675       res = buffer_allocate(scu);
676       if ( res == SUCCESS )
677         scu->flags |= READING;
678       else
679         return res;
680
681       scu->ctrl_byte = geomtab[scu->geometry].s_res;
682
683       /* initialize for pbm mode */
684       if ( scu->flags & PBM_MODE )
685         {
686           char *p;
687           int width = geomtab[scu->geometry].dpl;
688
689           sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height);
690           scu->bcount = scu->height * width / 8;
691
692           lprintf(("gsc%d.read: initializing pbm mode: `%s', bcount: 0x%x\n",
693                   unit, scu->sbuf.base, scu->bcount));
694
695           /* move header to end of sbuf */
696           for(p=scu->sbuf.base; *p; p++);
697           while(--p >= scu->sbuf.base)
698             {
699               *(char *)(scu->sbuf.base + --scu->sbuf.poi) = *p;
700               scu->bcount++;
701             }
702         }
703     }
704
705   lprintf(("gsc%d.read(before 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   if ( scu->sbuf.poi == scu->sbuf.size )
710     if ( (res = buffer_read(scu)) != SUCCESS )
711       return res;
712
713   lprintf(("gsc%d.read(after buffer_read): "
714           "size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
715           unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
716
717   nbytes = MIN( uio->uio_resid, scu->sbuf.size - scu->sbuf.poi );
718
719   if ( (scu->flags & PBM_MODE) )
720     nbytes = MIN( nbytes, scu->bcount );
721
722   lprintf(("gsc%d.read: transferring 0x%x bytes", unit, nbytes));
723
724   res = uiomove(scu->sbuf.base + scu->sbuf.poi, nbytes, uio);
725   if ( res != SUCCESS )
726     {
727       lprintf(("gsc%d.read: uiomove failed %d", unit, res));
728       return res;
729     }
730
731   scu->sbuf.poi += nbytes;
732   if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes;
733
734   lprintf(("gsc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n",
735           unit, scu->sbuf.size, scu->sbuf.poi, scu->bcount));
736
737   return SUCCESS;
738 }
739
740 /***********************************************************************
741  *
742  * gscioctl
743  *
744  */
745
746 static  int
747 gscioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
748 {
749   int unit = UNIT(minor(dev));
750   struct gsc_unit *scu = unittab + unit;
751
752   lprintf(("gsc%d.ioctl: minor %d\n",
753          unit, minor(dev)));
754
755   if ( unit >= NGSC || !( scu->flags & ATTACHED ) )
756     {
757       lprintf(("gsc%d.ioctl: unit was not attached successfully 0x%04x\n",
758              unit, scu->flags));
759       return ENXIO;
760     }
761
762   switch(cmd) {
763   case GSC_SRESSW:
764     lprintf(("gsc%d.ioctl:GSC_SRESSW\n", unit));
765     if ( scu->flags & READING )
766       {
767         lprintf(("gsc%d:ioctl on already reading unit\n", unit));
768         return EBUSY;
769       }
770     scu->geometry = get_geometry(scu);
771     return SUCCESS;
772   case GSC_GRES:
773     *(int *)data=geomtab[scu->geometry].dpi;
774     lprintf(("gsc%d.ioctl:GSC_GRES %ddpi\n", unit, *(int *)data));
775     return SUCCESS;
776   case GSC_GWIDTH:
777     *(int *)data=geomtab[scu->geometry].dpl;
778     lprintf(("gsc%d.ioctl:GSC_GWIDTH %d\n", unit, *(int *)data));
779     return SUCCESS;
780   case GSC_SRES:
781   case GSC_SWIDTH:
782     lprintf(("gsc%d.ioctl:GSC_SRES or GSC_SWIDTH %d\n",
783            unit, *(int *)data));
784     { int g;
785       struct gsc_geom geom = NEW_GEOM;
786       if ( cmd == GSC_SRES )
787         geom.dpi = *(int *)data;
788       else
789         geom.dpl = *(int *)data;
790       if ( ( g = lookup_geometry(geom, scu) ) == INVALID )
791         return EINVAL;
792       scu->geometry = g;
793       return SUCCESS;
794     }
795   case GSC_GHEIGHT:
796     *(int *)data=scu->height;
797     lprintf(("gsc%d.ioctl:GSC_GHEIGHT %d\n", unit, *(int *)data));
798     return SUCCESS;
799   case GSC_SHEIGHT:
800     lprintf(("gsc%d.ioctl:GSC_SHEIGHT %d\n", unit, *(int *)data));
801     if ( scu->flags & READING )
802       {
803         lprintf(("gsc%d:ioctl on already reading unit\n", unit));
804         return EBUSY;
805       }
806     scu->height=*(int *)data;
807     return SUCCESS;
808   case GSC_GBLEN:
809     *(int *)data=scu->blen;
810     lprintf(("gsc%d.ioctl:GSC_GBLEN %d\n", unit, *(int *)data));
811     return SUCCESS;
812   case GSC_SBLEN:
813     lprintf(("gsc%d.ioctl:GSC_SBLEN %d\n", unit, *(int *)data));
814     if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE)
815       {
816         lprintf(("gsc%d:ioctl buffer size too high\n", unit));
817         return ENOMEM;
818       }
819     scu->blen=*(int *)data;
820     return SUCCESS;
821   case GSC_GBTIME:
822     *(int *)data = scu->btime / hz;
823     lprintf(("gsc%d.ioctl:GSC_GBTIME %d\n", unit, *(int *)data));
824     return SUCCESS;
825   case GSC_SBTIME:
826     scu->btime = *(int *)data * hz;
827     lprintf(("gsc%d.ioctl:GSC_SBTIME %d\n", unit, *(int *)data));
828     return SUCCESS;
829   default: return ENOTTY;
830   }
831 }