File:  [DragonFly] / src / sys / dev / video / gsc / gsc.c
Revision 1.8: download - view: text, annotated - select for diffs
Thu May 13 23:49:22 2004 UTC (10 years, 3 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

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