Annotation of Net2/arch/i386/isa/lpa.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1990 William F. Jolitz, TeleMuse
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *   This software is a component of "386BSD" developed by 
        !            16:  *   William F. Jolitz, TeleMuse.
        !            17:  * 4. Neither the name of the developer nor the name "386BSD"
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ 
        !            22:  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS 
        !            23:  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. 
        !            24:  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT 
        !            25:  * NOT MAKE USE OF THIS WORK.
        !            26:  *
        !            27:  * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
        !            28:  * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN 
        !            29:  * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES 
        !            30:  * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING 
        !            31:  * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND 
        !            32:  * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE 
        !            33:  * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS 
        !            34:  * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
        !            35:  *
        !            36:  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
        !            37:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            38:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            39:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
        !            40:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            41:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            42:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            43:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            44:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            45:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            46:  * SUCH DAMAGE.
        !            47:  *
        !            48:  *     lpa.c,v 1.4 1993/06/05 22:58:29 cgd Exp
        !            49:  */
        !            50: 
        !            51: /*
        !            52:  * Device Driver for AT parallel printer port
        !            53:  * Written by William Jolitz 12/18/90
        !            54:  * Modified to run without interrupts
        !            55:  * 92-08-19  Wolfgang Stanglmeier  <[email protected]>
        !            56:  * Slight cleanup and reorganization, try to handle restarted syscalls
        !            57:  * 92-09-08  Andy Valencia <[email protected]>
        !            58:  * 93-04-08  Rodney W. Grimes <[email protected]>
        !            59:  * Converted to driver name lpa, shares lptreg.h with lpt.c, fixed probe
        !            60:  * so that it returns IO_LPTSIZE.  Added dummy lpaioctl.  Added my new
        !            61:  * probe code from lpt.c, as the one in here was crud.
        !            62:  */
        !            63: 
        !            64: #include "lpa.h"
        !            65: #if NLPA > 0
        !            66: 
        !            67: #include "param.h"
        !            68: #include "buf.h"
        !            69: #include "systm.h"
        !            70: #include "ioctl.h"
        !            71: #include "tty.h"
        !            72: #include "proc.h"
        !            73: #include "user.h"
        !            74: #include "uio.h"
        !            75: #include "kernel.h"
        !            76: #include "malloc.h"
        !            77: 
        !            78: #include "i386/isa/isa.h"
        !            79: #include "i386/isa/isa_device.h"
        !            80: #include "i386/isa/lptreg.h"
        !            81: 
        !            82: /* internal used flags */
        !            83: #define   OPEN        (0x01)   /* device is open */
        !            84: #define   INIT        (0x02)   /* device in open procedure */
        !            85: 
        !            86: /* flags from minor device */
        !            87: #define   LPA_PRIME   (0x20)   /* prime printer on open   */
        !            88: #define   LPA_ERROR   (0x10)   /* log error conditions    */
        !            89: 
        !            90: #define   LPA_FLAG(x) ((x) & 0xfc)
        !            91: #define   LPA_UNIT(x) ((x) & 0x03)
        !            92: 
        !            93: /* Printer Ready condition */
        !            94: #define   LPS_INVERT  (LPS_NBSY | LPS_NACK |           LPS_SEL | LPS_NERR)
        !            95: #define   LPS_MASK    (LPS_NBSY | LPS_NACK | LPS_OUT | LPS_SEL | LPS_NERR)
        !            96: #define   NOT_READY()   ((inb(sc->sc_stat)^LPS_INVERT)&LPS_MASK)
        !            97: 
        !            98: /* tsleep priority */
        !            99: #define   LPPRI       ((PZERO+8) | PCATCH)
        !           100: 
        !           101: /* debug flags */
        !           102: #ifndef DEBUG
        !           103: #define lprintf
        !           104: #else
        !           105: #define lprintf                if (lpaflag) printf
        !           106: int lpaflag = 1;
        !           107: #endif
        !           108: 
        !           109: int lpaprobe(), lpaattach();
        !           110: struct   isa_driver lpadriver = {lpaprobe, lpaattach, "lpa"};
        !           111: 
        !           112: /*
        !           113:  *   copy usermode data into sysmode buffer
        !           114:  */
        !           115: #define   BUFSIZE      1024
        !           116: 
        !           117: /*
        !           118: **   Waittimes
        !           119: */
        !           120: #define   TIMEOUT   (hz*16)   /* Timeout while open device */
        !           121: #define   LONG      (hz* 1)   /* Timesteps while open      */
        !           122: 
        !           123: #define   MAX_SPIN  255       /* max loop counter for busy wait */
        !           124: 
        !           125: struct lpa_softc {
        !           126:        char    *sc_cp;         /* current data to print        */
        !           127:        int     sc_count;       /* bytes queued in sc_inbuf     */
        !           128:        short   sc_data;        /* printer data port            */
        !           129:        short   sc_stat;        /* printer control port         */
        !           130:        short   sc_ctrl;        /* printer status port          */
        !           131:        u_char  sc_flags;       /* flags (open and internal)    */
        !           132:        u_char  sc_unit;        /* unit-number                  */
        !           133:        u_char  sc_smax;        /* current max busy loop cnt    */
        !           134:        char                    /* buffer for data              */
        !           135:         *sc_inbuf;
        !           136: } lpa_sc[NLPA];
        !           137: 
        !           138: /*
        !           139:  * Internal routine to lpaprobe to do port tests of one byte value
        !           140:  */
        !           141: int
        !           142: lpa_port_test(short port, u_char data, u_char mask)
        !           143:        {
        !           144:        int     temp, timeout;
        !           145: 
        !           146:        data = data & mask;
        !           147:        outb(port, data);
        !           148:        timeout = 100;
        !           149:        do
        !           150:                temp = inb(port) & mask;
        !           151:        while (temp != data && --timeout);
        !           152:        lprintf("Port 0x%x\tout=%x\tin=%x\n", port, data, temp);
        !           153:        return (temp == data);
        !           154:        }
        !           155: 
        !           156: /*
        !           157:  * New lpaprobe routine written by Rodney W. Grimes, 3/25/1993
        !           158:  *
        !           159:  * Logic:
        !           160:  *     1) You should be able to write to and read back the same value
        !           161:  *        to the data port.  Do an alternating zeros, alternating ones,
        !           162:  *        walking zero, and walking one test to check for stuck bits.
        !           163:  *
        !           164:  *     2) You should be able to write to and read back the same value
        !           165:  *        to the control port lower 5 bits, the upper 3 bits are reserved
        !           166:  *        per the IBM PC technical reference manauls and different boards
        !           167:  *        do different things with them.  Do an alternating zeros, alternating
        !           168:  *        ones, walking zero, and walking one test to check for stuck bits.
        !           169:  *
        !           170:  *        Some printers drag the strobe line down when the are powered off
        !           171:  *        so this bit has been masked out of the control port test.
        !           172:  *
        !           173:  *        XXX Some printers may not like a fast pulse on init or strobe, I
        !           174:  *        don't know at this point, if that becomes a problem these bits
        !           175:  *        should be turned off in the mask byte for the control port test.
        !           176:  *
        !           177:  *     3) Set the data and control ports to a value of 0
        !           178:  */
        !           179: 
        !           180: int
        !           181: lpaprobe(struct isa_device *dvp)
        !           182:        {
        !           183:        int     status;
        !           184:        short   port;
        !           185:        u_char  data;
        !           186:        u_char  mask;
        !           187:        int     i;
        !           188: 
        !           189:        status = IO_LPTSIZE;
        !           190: 
        !           191:        port = dvp->id_iobase + lpt_data;
        !           192:        mask = 0xff;
        !           193:        while (mask != 0)
        !           194:        {
        !           195:                data = 0x55;                            /* Alternating zeros */
        !           196:                if (!lpa_port_test(port, data, mask)) status = 0;
        !           197: 
        !           198:                data = 0xaa;                            /* Alternating ones */
        !           199:                if (!lpa_port_test(port, data, mask)) status = 0;
        !           200: 
        !           201:                for (i = 0; i < 8; i++)                 /* Walking zero */
        !           202:                        {
        !           203:                        data = ~(1 << i);
        !           204:                        if (!lpa_port_test(port, data, mask)) status = 0;
        !           205:                        }
        !           206: 
        !           207:                for (i = 0; i < 8; i++)                 /* Walking one */
        !           208:                        {
        !           209:                        data = (1 << i);
        !           210:                        if (!lpa_port_test(port, data, mask)) status = 0;
        !           211:                        }
        !           212: 
        !           213:                if (port == dvp->id_iobase + lpt_data)
        !           214:                        {
        !           215:                        port = dvp->id_iobase + lpt_control;
        !           216:                        mask = 0x1e;
        !           217:                        }
        !           218:                else
        !           219:                        mask = 0;
        !           220:                }
        !           221:        outb(dvp->id_iobase+lpt_data, 0);
        !           222:        outb(dvp->id_iobase+lpt_control, 0);
        !           223:        return (status);
        !           224:        }
        !           225: 
        !           226: /*
        !           227:  * lpaattach()
        !           228:  *     Install device
        !           229:  */
        !           230: lpaattach(isdp)
        !           231:        struct isa_device *isdp;
        !           232: {
        !           233:        struct   lpa_softc   *sc;
        !           234: 
        !           235:        sc = lpa_sc + isdp->id_unit;
        !           236:        sc->sc_unit = isdp->id_unit;
        !           237:        sc->sc_data = isdp->id_iobase + lpt_data;
        !           238:        sc->sc_stat = isdp->id_iobase + lpt_status;
        !           239:        sc->sc_ctrl = isdp->id_iobase + lpt_control;
        !           240:        outb(sc->sc_ctrl, LPC_NINIT);
        !           241:        return (1);
        !           242: }
        !           243: 
        !           244: /*
        !           245:  * lpaopen()
        !           246:  *     New open on device.
        !           247:  *
        !           248:  * We forbid all but first open
        !           249:  */
        !           250: lpaopen(dev, flag)
        !           251:        dev_t dev;
        !           252:        int flag;
        !           253: {
        !           254:        struct lpa_softc *sc;
        !           255:        int delay;      /* slept time in 1/hz seconds of tsleep */
        !           256:        int err;
        !           257:        u_char sta, unit;
        !           258: 
        !           259:        unit= LPA_UNIT(minor(dev));
        !           260:        sta = LPA_FLAG(minor(dev));
        !           261: 
        !           262:        /* minor number out of limits ? */
        !           263:        if (unit >= NLPA)
        !           264:                return (ENXIO);
        !           265:        sc = lpa_sc + unit;
        !           266: 
        !           267:        /* Attached ? */
        !           268:        if (!sc->sc_ctrl) { /* not attached */
        !           269:                return(ENXIO);
        !           270:        }
        !           271: 
        !           272:        /* Printer busy ? */
        !           273:        if (sc->sc_flags) { /* too late .. */
        !           274:                return(EBUSY);
        !           275:        }
        !           276: 
        !           277:        /* Have memory for buffer? */
        !           278:        sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
        !           279:        if (sc->sc_inbuf == 0)
        !           280:                return(ENOMEM);
        !           281: 
        !           282:        /* Init printer */
        !           283:        sc->sc_flags = sta | INIT;
        !           284:        if (sc->sc_flags & LPA_PRIME) {
        !           285:                outb(sc->sc_ctrl, 0);
        !           286:        }
        !           287: 
        !           288:        /* Select printer */
        !           289:        outb(sc->sc_ctrl, LPC_SEL|LPC_NINIT);
        !           290: 
        !           291:        /* and wait for ready .. */
        !           292:        for (delay=0; NOT_READY(); delay+= LONG) {
        !           293:                if (delay >= TIMEOUT) { /* too long waited .. */
        !           294:                        sc->sc_flags = 0;
        !           295:                        return (EBUSY);
        !           296:                }
        !           297: 
        !           298:                /* sleep a moment */
        !           299:                if ((err = tsleep (sc, LPPRI, "lpa: open", LONG)) !=
        !           300:                                EWOULDBLOCK) {
        !           301:                        sc->sc_flags = 0;
        !           302:                        return (EBUSY);
        !           303:                }
        !           304:        }
        !           305: 
        !           306:        /* Printer ready .. set variables */
        !           307:        sc->sc_flags |= OPEN;
        !           308:        sc->sc_count = 0;
        !           309: 
        !           310:        return(0);
        !           311: }
        !           312: 
        !           313: /*
        !           314:  * pushbytes()
        !           315:  *     Workhorse for actually spinning and writing bytes to printer
        !           316:  */
        !           317: static
        !           318: pushbytes(sc)
        !           319:        struct lpa_softc *sc;
        !           320: {
        !           321:        int spin, err, tic;
        !           322:        char ch;
        !           323: 
        !           324:        /* loop for every character .. */
        !           325:        while (sc->sc_count > 0) {
        !           326:                /* printer data */
        !           327:                ch = *(sc->sc_cp);
        !           328:                sc->sc_cp += 1;
        !           329:                sc->sc_count -= 1;
        !           330:                outb(sc->sc_data, ch);
        !           331: 
        !           332:                /* Busy wait for printer ready .. */
        !           333:                spin = tic = 0;
        !           334:                while (NOT_READY()) {
        !           335:                        if (++spin >= sc->sc_smax) {
        !           336:                                /*
        !           337:                                 * Now sleep, every cycle a
        !           338:                                 * little longer ..
        !           339:                                 */
        !           340:                                tic = tic + tic + 1;
        !           341:                                err = tsleep(sc, LPPRI, "lpa: write", tic);
        !           342:                                if (err != EWOULDBLOCK) {
        !           343:                                        return (err);
        !           344:                                }
        !           345:                        }
        !           346:                }
        !           347: 
        !           348:                /* strobe */
        !           349:                outb(sc->sc_ctrl, LPC_NINIT|LPC_SEL|LPC_STB);
        !           350:                outb(sc->sc_ctrl, LPC_NINIT|LPC_SEL);
        !           351: 
        !           352:                /* Adapt busy-wait length... */
        !           353:                if (spin >= sc->sc_smax) { /* was sleep wait */
        !           354:                        if (sc->sc_smax<MAX_SPIN)
        !           355:                                sc->sc_smax++;
        !           356:                }
        !           357:                if (spin*2 < sc->sc_smax) {
        !           358:                        sc->sc_smax--;
        !           359:                }
        !           360:        }
        !           361:        return(0);
        !           362: }
        !           363: 
        !           364: /*
        !           365:  * lpaclose()
        !           366:  *     Close on lp.  Try to flush data in buffer out.
        !           367:  */
        !           368: lpaclose(dev, flag)
        !           369:        dev_t dev;
        !           370:        int flag;
        !           371: {
        !           372:        struct lpa_softc *sc = lpa_sc + LPA_UNIT(minor(dev));
        !           373: 
        !           374:        /* If there's queued data, try to flush it */
        !           375:        (void)pushbytes(sc);
        !           376: 
        !           377:        /* really close .. quite simple :-)  */
        !           378:        outb(sc->sc_ctrl, LPC_NINIT);
        !           379:        sc->sc_flags = 0;
        !           380:        free(sc->sc_inbuf, M_DEVBUF);
        !           381:        sc->sc_inbuf = 0;       /* Sanity */
        !           382:        return(0);
        !           383: }
        !           384: 
        !           385: /*
        !           386:  * lpawrite()
        !           387:  *     Copy from user's buffer, then print
        !           388:  */
        !           389: lpawrite(dev, uio)
        !           390:        dev_t dev;
        !           391:        struct uio *uio;
        !           392: {
        !           393:        struct lpa_softc *sc = lpa_sc + LPA_UNIT(minor(dev));
        !           394:        int err;
        !           395: 
        !           396:        /* Write out old bytes from interrupted syscall */
        !           397:        if (sc->sc_count > 0) {
        !           398:                err = pushbytes(sc);
        !           399:                if (err)
        !           400:                        return(err);
        !           401:        }
        !           402: 
        !           403:        /* main loop */
        !           404:        while ((sc->sc_count = MIN(BUFSIZE, uio->uio_resid)) > 0) {
        !           405:                /*  get from user-space  */
        !           406:                sc->sc_cp = sc->sc_inbuf;
        !           407:                uiomove(sc->sc_inbuf, sc->sc_count, uio);
        !           408:                err = pushbytes(sc);
        !           409:                if (err)
        !           410:                        return(err);
        !           411:        }
        !           412:        return(0);
        !           413: }
        !           414: 
        !           415: int
        !           416: lpaioctl(dev_t dev, int cmd, caddr_t data, int flag)
        !           417: {
        !           418:        int     error;
        !           419: 
        !           420:        error = 0;
        !           421:        switch (cmd) {
        !           422: #ifdef THISISASAMPLE
        !           423:        case XXX:
        !           424:                dothis; andthis; andthat;
        !           425:                error=x;
        !           426:                break;
        !           427: #endif /* THISISASAMPLE */
        !           428:        default:
        !           429:                error = ENODEV;
        !           430:        }
        !           431: 
        !           432:        return(error);
        !           433: }
        !           434: 
        !           435: #endif /* NLPA > 0 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.