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