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