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

unix.superglobalmegacorp.com

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