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