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