Annotation of coherent/b/STREAMS/io.386/lp386.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * This is a driver for PC parallel printers.
        !             3:  * It has been tested on an EPSON MX-80, Printronix P300, HP LaserJet II.
        !             4:  * Supports up to three line printers.
        !             5:  */
        !             6: #include <sys/coherent.h>
        !             7: #include <sys/con.h>
        !             8: #include <sys/devices.h>
        !             9: #include <sys/errno.h>
        !            10: #include <sys/io.h>
        !            11: #include <sys/proc.h>
        !            12: #include <sys/sched.h>
        !            13: #include <sys/stat.h>
        !            14: 
        !            15: /*
        !            16:  * Patchable parameters.
        !            17:  *
        !            18:  *     LP0_OK specifies whether LP0 is always THERE.
        !            19:  *     LPTIME specifies number of ticks between polls.
        !            20:  *     LPWAIT specifies loop counter to wait in poll.
        !            21:  *     LPTEST specifies whether or not to test for on-line conditition.
        !            22:  */
        !            23: int    LP0_OK = 0;
        !            24: int    LPTIME = 4;
        !            25: int    LPWAIT = 400;
        !            26: int    LPTEST = 1;
        !            27: 
        !            28: /*
        !            29:  * Driver configuration.
        !            30:  */
        !            31: int    lpload();
        !            32: int    lpunload();
        !            33: int    lpwrite();
        !            34: int    lpopen();
        !            35: int    lpclose();
        !            36: int    lpintr();
        !            37: int    nulldev();
        !            38: int    nonedev();
        !            39: 
        !            40: CON    lpcon = {
        !            41:        DFCHR,                          /* Flags */
        !            42:        LP_MAJOR,                               /* Major index */
        !            43:        lpopen,                         /* Open */
        !            44:        lpclose,                        /* Close */
        !            45:        nulldev,                        /* Block */
        !            46:        nonedev,                        /* Read */
        !            47:        lpwrite,                        /* Write */
        !            48:        nonedev,                        /* Ioctl */
        !            49:        nulldev,                        /* Powerfail */
        !            50:        nulldev,                        /* Timeout */
        !            51:        lpload,                         /* Load */
        !            52:        lpunload                        /* Unload */
        !            53: };
        !            54: 
        !            55: /*
        !            56:  * Line Printer Registers.
        !            57:  */
        !            58: #define        LPDAT   (0)                     /* Data port, lpbase + 0 */
        !            59: #define        LPSTR   (1)                     /* Status port, lpbase + 1 */
        !            60: #define        LPCSR   (2)                     /* Control port, lpbase + 2 */
        !            61: 
        !            62: /*
        !            63:  * LP Flag Bits.
        !            64:  */
        !            65: #define        LPTHERE 0x01                    /* Interface actually there */
        !            66: #define        LPOPEN  0x02                    /* Printer is open */
        !            67: #define        LPSLEEP 0x04                    /* Sleeping on buffer event */
        !            68: #define        LPRAW   0x80                    /* Raw mode */
        !            69: 
        !            70: /*
        !            71:  * Printer database.
        !            72:  * Terminated by lpbase = 0.
        !            73:  * NLP = # entries - 1.
        !            74:  */
        !            75: static struct  lpinfo  {
        !            76:        int     lpbase;                 /* I/O Base address */
        !            77:        int     lpflag;                 /* Flags */
        !            78:        int     lpcol;                  /* Current horizontal position */
        !            79: }      lpinfo[] = {
        !            80:        {       0x3BC   },
        !            81:        {       0x378   },
        !            82:        {       0x278   },
        !            83:        {       0x000   }
        !            84: };
        !            85: #define        NLP     (sizeof(lpinfo) / sizeof(lpinfo[0]) - 1)
        !            86: 
        !            87: /*
        !            88:  * LP Status Register Bits.
        !            89:  */
        !            90: #define        ACK     0x80                    /* Ack (active high) */
        !            91: #define        BUSY    0x40                    /* Busy (active high) */
        !            92: #define        NOPAPER 0x20                    /* No paper */
        !            93: #define        ONLINE  0x10                    /* On line */
        !            94: #define        NERROR  0x08                    /* Error (active low) */
        !            95: 
        !            96: /* IBM cable */
        !            97: #define        IBMNBSY 0x80                    /* Busy (active low) */
        !            98: #define        IBMNACK 0x40                    /* Ack (active low) */
        !            99: 
        !           100: /*
        !           101:  * LP Control Register Bits.
        !           102:  */
        !           103: #define        IENABLE 0x10                    /* Interrupt enable */
        !           104: #define        SEL     0x08                    /* Select input */
        !           105: #define        NINIT   0x04                    /* Initialise printer (active low) */
        !           106: #define        AFEED   0x02                    /* Auto line feed */
        !           107: #define        STROBE  0x01                    /* Strobe */
        !           108: 
        !           109: /*
        !           110:  * On load
        !           111:  * compute the port addresses,
        !           112:  * reset the printer, and select it.
        !           113:  */
        !           114: static
        !           115: lpload()
        !           116: {
        !           117:        register struct lpinfo * p;
        !           118:        register int delay;
        !           119:        static int notfirst;
        !           120: 
        !           121:        /*
        !           122:         * Only initialize hardware on first invocation.
        !           123:         * Necessary if used as console device [condev].
        !           124:         */
        !           125:        if (notfirst)
        !           126:                return;
        !           127:        notfirst = 1;
        !           128: 
        !           129:        /*
        !           130:         * Note: since some PC clones lp ports can't be read,
        !           131:         * their lpflag field has to be patched to 'LPTHERE'.
        !           132:         */
        !           133:        if (LP0_OK & 1)
        !           134:                lpinfo[0].lpflag |= LPTHERE;
        !           135:        if (LP0_OK & 2)
        !           136:                lpinfo[1].lpflag |= LPTHERE;
        !           137:        if (LP0_OK & 4)
        !           138:                lpinfo[2].lpflag |= LPTHERE;
        !           139: 
        !           140:        for (p = lpinfo; p->lpbase ; ++p) {
        !           141: 
        !           142:                /*
        !           143:                 * Check printer port existence.
        !           144:                 */
        !           145:                if ((p->lpflag & LPTHERE) == 0) {
        !           146:                        outb(p->lpbase+LPDAT, 0xA5);
        !           147:                        delay = LPWAIT; do {
        !           148:                        } while (--delay);
        !           149:                        if (inb(p->lpbase+LPDAT) == 0xA5)
        !           150:                                p->lpflag |= LPTHERE;
        !           151:                }
        !           152: 
        !           153:                /*
        !           154:                 * Initialize and select printer.
        !           155:                 */
        !           156:                outb(p->lpbase+LPCSR, SEL);
        !           157:                delay = LPWAIT; do {
        !           158:                } while (--delay);
        !           159:                outb(p->lpbase+LPCSR, SEL|NINIT);
        !           160:        }
        !           161: }
        !           162: 
        !           163: /*
        !           164:  * On unload
        !           165:  * cancel any timed functions.
        !           166:  */
        !           167: static
        !           168: lpunload()
        !           169: {
        !           170:        lptimer();
        !           171: }
        !           172: 
        !           173: /*
        !           174:  * The open routine makes sure that
        !           175:  * only one process has the printer open
        !           176:  * at one time, and not too much else.
        !           177:  */
        !           178: static
        !           179: lpopen(dev, mode)
        !           180: dev_t  dev;
        !           181: {
        !           182:        register struct lpinfo * p;
        !           183: 
        !           184:        /*
        !           185:         * Illegal printer port.
        !           186:         */
        !           187:        if ((minor(dev) & ~LPRAW) >= NLP) {
        !           188:                u.u_error = ENXIO;
        !           189:                return;
        !           190:        }
        !           191: 
        !           192:        /*
        !           193:         * Access attributes.
        !           194:         */
        !           195:        p = &lpinfo[ minor(dev) & ~LPRAW ];
        !           196: 
        !           197:        /*
        !           198:         * Attempt initialization if printer port not found.
        !           199:         */
        !           200:        if ((p->lpflag&LPTHERE) == 0)
        !           201:                lpload();
        !           202: 
        !           203:        /*
        !           204:         * Printer port not found.
        !           205:         */
        !           206:        if ((p->lpflag&LPTHERE) == 0) {
        !           207:                u.u_error = ENXIO;
        !           208:                return;
        !           209:        }
        !           210: 
        !           211:        /*
        !           212:         * Printer port already open.
        !           213:         */
        !           214:        if ((p->lpflag&LPOPEN) != 0) {
        !           215:                u.u_error = EBUSY;
        !           216:                return;
        !           217:        }
        !           218: 
        !           219:        /*
        !           220:         * Printer powered off or off-line
        !           221:         */
        !           222:        if (LPTEST && !(inb(p->lpbase+LPSTR) & ONLINE)) {
        !           223:                u.u_error = EIO;
        !           224:                return;
        !           225:        }
        !           226: 
        !           227:        /*
        !           228:         * Flag port as being open.
        !           229:         */
        !           230:        p->lpflag &= ~LPRAW;
        !           231:        p->lpflag |= LPOPEN | minor(dev) & LPRAW;
        !           232: 
        !           233:        /*
        !           234:         * Initiate periodic printer scan if user open.
        !           235:         */
        !           236:        if ((SELF != NULL) && (SELF->p_pid != 0))
        !           237:                lptimer();
        !           238: }
        !           239: 
        !           240: /*
        !           241:  * The close routine marks the device as no longer open.
        !           242:  */
        !           243: static
        !           244: lpclose(dev)
        !           245: dev_t  dev;
        !           246: {
        !           247:        lpinfo[ minor(dev) & ~LPRAW ].lpflag &= ~LPOPEN;
        !           248: }
        !           249: 
        !           250: /*
        !           251:  * The write routine copies the
        !           252:  * characters from the user buffer to
        !           253:  * the printer buffer, expanding tabs and
        !           254:  * keeping track of the current horizontal
        !           255:  * position of the print head.
        !           256:  */
        !           257: static
        !           258: lpwrite(dev, iop)
        !           259: dev_t  dev;
        !           260: IO     *iop;
        !           261: {
        !           262:        register struct lpinfo * p;
        !           263:        register int    c;
        !           264: 
        !           265:        p = &lpinfo[ minor(dev) & ~LPRAW ];
        !           266: 
        !           267:        /*
        !           268:         * Writes from kernel are handled via busy-waits instead of timeouts.
        !           269:         */
        !           270:        if (iop->io_seg == IOSYS) {
        !           271: 
        !           272:                while ((c=iogetc(iop)) >= 0) {
        !           273: 
        !           274:                        while ((inb(p->lpbase+LPSTR) & IBMNBSY) == 0)
        !           275:                                ;
        !           276: 
        !           277:                        outb(p->lpbase+LPDAT, c);
        !           278:                        outb(p->lpbase+LPCSR, SEL|NINIT|STROBE);
        !           279:                        outb(p->lpbase+LPCSR, SEL|NINIT);
        !           280:                }
        !           281:                return;
        !           282:        }
        !           283: 
        !           284:        /*
        !           285:         * Writes from user are handled via lpchar() which uses timeouts.
        !           286:         */
        !           287:        while ((c=iogetc(iop)) >= 0) {
        !           288: 
        !           289:                if ((p->lpflag&LPRAW) == 0) {
        !           290: 
        !           291:                        switch (c) {
        !           292: 
        !           293:                        case '\t':
        !           294:                                do {
        !           295:                                        lpchar(p, ' ');
        !           296:                                } while ((++p->lpcol&07) != 0);
        !           297:                                continue;
        !           298:        
        !           299:                        case '\n':
        !           300:                                lpchar(p, '\r');
        !           301:                                /* no break */
        !           302: 
        !           303:                        case '\r':
        !           304:                        case '\f':
        !           305:                                p->lpcol = 0;
        !           306:                                break;
        !           307:        
        !           308:                        case '\b':
        !           309:                                --p->lpcol;
        !           310:                                break;
        !           311:        
        !           312:                        default:
        !           313:                                ++p->lpcol;
        !           314:                        }
        !           315:                }
        !           316:                lpchar(p, c);
        !           317:        }
        !           318: }
        !           319: 
        !           320: /*
        !           321:  * Put a character into the printer buffer.
        !           322:  * If the printer doesn't respond ready in a reasonable time
        !           323:  * sleep for a while.
        !           324:  */
        !           325: static
        !           326: lpchar(p, c)
        !           327: register struct lpinfo *p;
        !           328: int c;
        !           329: {
        !           330:        register int    waitCount;
        !           331:        register int    s;
        !           332: 
        !           333:        waitCount = LPWAIT;
        !           334:        while ((inb(p->lpbase+LPSTR) & IBMNBSY) == 0) {
        !           335:                if (--waitCount == 0) {
        !           336:                        s = sphi();
        !           337:                        p->lpflag |= LPSLEEP;
        !           338:                        x_sleep((char *)p, pritty, slpriSigLjmp, "lpchar");
        !           339:                        spl(s);
        !           340:                        waitCount = LPWAIT;
        !           341:                }
        !           342:        }
        !           343: 
        !           344:        outb(p->lpbase+LPDAT, c);
        !           345:        outb(p->lpbase+LPCSR, SEL|NINIT|STROBE);
        !           346:        outb(p->lpbase+LPCSR, SEL|NINIT);
        !           347: }
        !           348: 
        !           349: /*
        !           350:  * Poll the line printer interface from the clock.
        !           351:  * Turn it off when there is nothing left to do.
        !           352:  */
        !           353: static
        !           354: lptimer()
        !           355: {
        !           356:        register struct lpinfo *p;
        !           357:        int isopen = 0;
        !           358:        static TIM tim;
        !           359: 
        !           360:        /*
        !           361:         * Scan all printers.
        !           362:         */
        !           363:        for (p = lpinfo; p->lpbase; ++p) {
        !           364: 
        !           365:                /*
        !           366:                 * Ignore unopened printers.
        !           367:                 */
        !           368:                if ((p->lpflag & LPOPEN) == 0)
        !           369:                        continue;
        !           370: 
        !           371:                ++isopen;
        !           372: 
        !           373:                /*
        !           374:                 * Check for sleeping process on ready printer.
        !           375:                 */
        !           376:                if((p->lpflag & LPSLEEP) && (inb(p->lpbase+LPSTR) & IBMNBSY)){
        !           377:                        p->lpflag &= ~LPSLEEP;
        !           378:                        wakeup((char *)p);
        !           379:                }
        !           380:        }
        !           381: 
        !           382:        /*
        !           383:         * Reschedule timer function if at least 1 printer is still open.
        !           384:         */
        !           385:        if (isopen)
        !           386:                timeout(&tim, LPTIME, lptimer, &tim);
        !           387: }

unix.superglobalmegacorp.com

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