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