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