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