FreeBSD/Linux Kernel Cross Reference
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 * $FreeBSD$
35 *
36 */
37
38 #include "gsc.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/conf.h>
42 #include <sys/buf.h>
43 #include <sys/malloc.h>
44 #include <sys/kernel.h>
45 #include <sys/uio.h>
46
47 #include <machine/gsc.h>
48
49 #include <i386/isa/isa.h>
50 #include <i386/isa/isa_device.h>
51 #include <i386/isa/gscreg.h>
52
53 /***********************************************************************
54 *
55 * CONSTANTS & DEFINES
56 *
57 ***********************************************************************/
58
59 #define PROBE_FAIL 0
60 #define PROBE_SUCCESS IO_GSCSIZE
61 #define ATTACH_FAIL 0
62 #define ATTACH_SUCCESS 1
63 #define SUCCESS 0
64 #define FAIL -1
65 #define INVALID FAIL
66
67 #define DMA1_READY 0x08
68
69 #ifdef GSCDEBUG
70 #define lprintf(args) \
71 do { \
72 if (scu->flags & FLAG_DEBUG) \
73 printf args; \
74 } while (0)
75 #else
76 #define lprintf(args)
77 #endif
78
79 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
80
81 #define TIMEOUT (hz*15) /* timeout while reading a buffer - default value */
82 #define LONG (hz/60) /* timesteps while reading a buffer */
83 #define GSCPRI PRIBIO /* priority while reading a buffer */
84
85 /***********************************************************************
86 *
87 * LAYOUT OF THE MINOR NUMBER
88 *
89 ***********************************************************************/
90
91 #define UNIT_MASK 0xc0 /* unit gsc0 .. gsc3 */
92 #define UNIT(x) (x >> 6)
93 #define DBUG_MASK 0x20
94 #define FRMT_MASK 0x18 /* output format */
95 #define FRMT_RAW 0x00 /* output bits as read from scanner */
96 #define FRMT_GRAY 0x10 /* output graymap (not implemented yet) */
97 #define FRMT_PBM 0x08 /* output pbm format */
98 #define FRMT_PGM 0x18
99
100 /***********************************************************************
101 *
102 * THE GEMOMETRY TABLE
103 *
104 ***********************************************************************/
105
106 #define GEOMTAB_SIZE 7
107
108 static const struct gsc_geom {
109 int dpi; /* dots per inch */
110 int dpl; /* dots per line */
111 int g_res; /* get resolution value (status flag) */
112 int s_res; /* set resolution value (control register) */
113 } geomtab[GEOMTAB_SIZE] = {
114 { 100, 424, GSC_RES_100, GSC_CNT_424},
115 { 200, 840, GSC_RES_200, GSC_CNT_840},
116 { 300, 1264, GSC_RES_300, GSC_CNT_1264},
117 { 400, 1648, GSC_RES_400, GSC_CNT_1648},
118 { -1, 1696, -1, GSC_CNT_1696},
119 { -2, 2644, -2, GSC_CNT_2544},
120 { -3, 3648, -3, GSC_CNT_3648},
121 };
122
123 #define NEW_GEOM { INVALID, INVALID, INVALID, INVALID }
124
125 /***********************************************************************
126 *
127 * THE TABLE OF UNITS
128 *
129 ***********************************************************************/
130
131 struct _sbuf {
132 size_t size;
133 size_t poi;
134 char *base;
135 };
136
137 struct gsc_unit {
138 int channel; /* DMA channel */
139 int data; /* - video port */
140 int stat; /* - status port */
141 int ctrl; /* - control port */
142 int clrp; /* - clear port */
143 int flags;
144 #define ATTACHED 0x01
145 #define OPEN 0x02
146 #define READING 0x04
147 #define EOF 0x08
148 #define FLAG_DEBUG 0x10
149 #define PBM_MODE 0x20
150 int geometry; /* resolution as geomtab index */
151 int blen; /* length of buffer in lines */
152 int btime; /* timeout of buffer in seconds/hz */
153 struct _sbuf sbuf;
154 char ctrl_byte; /* the byte actually written to ctrl port */
155 int height; /* height, for pnm modes */
156 size_t bcount; /* bytes to read, for pnm modes */
157 struct _sbuf hbuf; /* buffer for pnm header data */
158 };
159
160 static struct gsc_unit unittab[NGSC];
161
162 /* I could not find a reasonable buffer size limit other than by
163 * experiments. MAXPHYS is obviously too much, while DEV_BSIZE and
164 * PAGE_SIZE are really too small. There must be something wrong
165 * with isa_dmastart/isa_dmarangecheck HELP!!!
166 */
167 #define MAX_BUFSIZE 0x3000
168 #define DEFAULT_BLEN 59
169
170 /***********************************************************************
171 *
172 * THE PER-DRIVER RECORD FOR ISA.C
173 *
174 ***********************************************************************/
175
176 static int gscprobe (struct isa_device *isdp);
177 static int gscattach(struct isa_device *isdp);
178
179 struct isa_driver gscdriver = { gscprobe, gscattach, "gsc" };
180
181 static d_open_t gscopen;
182 static d_close_t gscclose;
183 static d_read_t gscread;
184 static d_ioctl_t gscioctl;
185
186 #define CDEV_MAJOR 47
187 static struct cdevsw gsc_cdevsw = {
188 /* open */ gscopen,
189 /* close */ gscclose,
190 /* read */ gscread,
191 /* write */ nowrite,
192 /* ioctl */ gscioctl,
193 /* poll */ nopoll,
194 /* mmap */ nommap,
195 /* strategy */ nostrategy,
196 /* name */ "gsc",
197 /* maj */ CDEV_MAJOR,
198 /* dump */ nodump,
199 /* psize */ nopsize,
200 /* flags */ 0,
201 /* bmaj */ -1
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, GSCPRI | 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 proc *p)
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 proc *p)
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 proc *p)
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 }
Cache object: f17bdb0c4e231d92cb14bf40816c643a
|