The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/gsc.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: c8a5f0ac14f0381953279374691a5971


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.