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-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
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$
   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/buf.h>
   43 #include <sys/malloc.h>
   44 #include <sys/kernel.h>
   45 #include <sys/uio.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 /***********************************************************************
   54  *
   55  * CONSTANTS & DEFINES
   56  *
   57  ***********************************************************************/
   58 
   59 #define PROBE_FAIL    0
   60 #define PROBE_SUCCESS IO_GSCSIZE
   61 #define ATTACH_FAIL   0
   62 #define ATTACH_SUCCESS 1
   63 #define SUCCESS       0
   64 #define FAIL         -1
   65 #define INVALID       FAIL
   66 
   67 #define DMA1_READY  0x08
   68 
   69 #ifdef GSCDEBUG
   70 #define lprintf(args)                                           \
   71                 do {                                            \
   72                         if (scu->flags & FLAG_DEBUG)            \
   73                                 printf args;                    \
   74                 } while (0)
   75 #else
   76 #define lprintf(args)
   77 #endif
   78 
   79 #define MIN(a, b)       (((a) < (b)) ? (a) : (b))
   80 
   81 #define TIMEOUT (hz*15)  /* timeout while reading a buffer - default value */
   82 #define LONG    (hz/60)  /* timesteps while reading a buffer */
   83 #define GSCPRI  PRIBIO   /* priority while reading a buffer */
   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 
  108 static 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 
  131 struct _sbuf {
  132   size_t  size;
  133   size_t  poi;
  134   char   *base;
  135 };
  136 
  137 struct 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 
  160 static 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 
  176 static  int gscprobe (struct isa_device *isdp);
  177 static  int gscattach(struct isa_device *isdp);
  178 
  179 struct isa_driver gscdriver = { gscprobe, gscattach, "gsc" };
  180 
  181 static  d_open_t        gscopen;
  182 static  d_close_t       gscclose;
  183 static  d_read_t        gscread;
  184 static  d_ioctl_t       gscioctl;
  185 
  186 #define CDEV_MAJOR 47
  187 static struct cdevsw gsc_cdevsw = {
  188         /* open */      gscopen,
  189         /* close */     gscclose,
  190         /* read */      gscread,
  191         /* write */     nowrite,
  192         /* ioctl */     gscioctl,
  193         /* poll */      nopoll,
  194         /* mmap */      nommap,
  195         /* strategy */  nostrategy,
  196         /* name */      "gsc",
  197         /* maj */       CDEV_MAJOR,
  198         /* dump */      nodump,
  199         /* psize */     nopsize,
  200         /* flags */     0,
  201         /* bmaj */      -1
  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, GSCPRI | 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 proc *p)
  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 proc *p)
  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 proc *p)
  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 }

Cache object: f17bdb0c4e231d92cb14bf40816c643a


[ 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.