示例#1
0
static inline int lp_char_polled(char lpchar, int minor)
{
	int status, wait = 0;
	unsigned long count  = 0;
	struct lp_stats *stats;

	do {
		status = LP_S(minor);
		count ++;
		if(need_resched)
			schedule();
	} while(!LP_READY(minor,status) && count < LP_CHAR(minor));

	if (count == LP_CHAR(minor)) {
		return 0;
		/* we timed out, and the character was /not/ printed */
	}
	outb_p(lpchar, LP_B(minor));
	stats = &LP_STAT(minor);
	stats->chars++;
	/* must wait before taking strobe high, and after taking strobe
	   low, according spec.  Some printers need it, others don't. */
	while(wait != LP_WAIT(minor)) wait++;
	/* control port takes strobe high */
	outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
	while(wait) wait--;
	/* take strobe low */
	outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
	/* update waittime statistics */
	if (count > stats->maxwait) {
#ifdef LP_DEBUG
	    printk(KERN_DEBUG "lp%d success after %d counts.\n",minor,count);
#endif
	    stats->maxwait = count;
	}
	count *= 256;
	wait = (count > stats->meanwait)? count - stats->meanwait :
					  stats->meanwait - count;
	stats->meanwait = (255*stats->meanwait + count + 128) / 256;
	stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;

	return 1;
}
示例#2
0
static inline int lp_char_interrupt(char lpchar, int minor)
{
    int wait;
    unsigned long count = 0;
    unsigned char status;
    struct lp_stats *stats;

    do {
        if(need_resched)
            schedule();
        if ((status = LP_S(minor)) & LP_PBUSY) {
            if (!LP_CAREFUL_READY(minor, status))
                return 0;
            outb_p(lpchar, LP_B(minor));
            stats = &LP_STAT(minor);
            stats->chars++;
            /* must wait before taking strobe high, and after taking strobe
               low, according spec.  Some printers need it, others don't. */
            wait = 0;
            while(wait != LP_WAIT(minor)) wait++;
            /* control port takes strobe high */
            outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
            while(wait) wait--;
            /* take strobe low */
            outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
            /* update waittime statistics */
            if (count) {
                if (count > stats->maxwait)
                    stats->maxwait = count;
                count *= 256;
                wait = (count > stats->meanwait)? count - stats->meanwait :
                       stats->meanwait - count;
                stats->meanwait = (255*stats->meanwait + count + 128) / 256;
                stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
            }
            return 1;
        }
    } while (count++ < LP_CHAR(minor));

    return 0;
}
示例#3
0
static int lp_ioctl(struct inode *inode, struct file *file,
		    unsigned int cmd, unsigned long arg)
{
	unsigned int minor = MINOR(inode->i_rdev);
	int retval = 0;

#ifdef LP_DEBUG
	printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
#endif
	if (minor >= LP_NO)
		return -ENODEV;
	if ((LP_F(minor) & LP_EXIST) == 0)
		return -ENODEV;
	switch ( cmd ) {
		case LPTIME:
			LP_TIME(minor) = arg * HZ/100;
			break;
		case LPCHAR:
			LP_CHAR(minor) = arg;
			break;
		case LPABORT:
			if (arg)
				LP_F(minor) |= LP_ABORT;
			else
				LP_F(minor) &= ~LP_ABORT;
			break;
		case LPABORTOPEN:
			if (arg)
				LP_F(minor) |= LP_ABORTOPEN;
			else
				LP_F(minor) &= ~LP_ABORTOPEN;
			break;
		case LPCAREFUL:
			if (arg)
				LP_F(minor) |= LP_CAREFUL;
			else
				LP_F(minor) &= ~LP_CAREFUL;
			break;
		case LPWAIT:
			LP_WAIT(minor) = arg;
			break;
		case LPSETIRQ: {
			int oldirq;
			int newirq = arg;
			struct lp_struct *lp = &lp_table[minor];

			if (!suser())
				return -EPERM;

			oldirq = LP_IRQ(minor);

			/* Allocate buffer now if we are going to need it */
			if (!oldirq && newirq) {
				lp->lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
				if (!lp->lp_buffer)
					return -ENOMEM;
			}

			if (oldirq) {
				free_irq(oldirq, NULL);
			}
			if (newirq) {
				/* Install new irq */
				if ((retval = request_irq(newirq, lp_interrupt, SA_INTERRUPT, "printer", NULL))) {
					if (oldirq) {
						/* restore old irq */
						request_irq(oldirq, lp_interrupt, SA_INTERRUPT, "printer", NULL);
					} else {
						/* We don't need the buffer */
						kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
						lp->lp_buffer = NULL;
					}
					return retval;
				}
			}
			if (oldirq && !newirq) {
				/* We don't need the buffer */
				kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
				lp->lp_buffer = NULL;
			}
			LP_IRQ(minor) = newirq;
			lp_reset(minor);
			break;
		}
		case LPGETIRQ:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
			    sizeof(int));
		    	if (retval)
		    		return retval;
			memcpy_tofs((int *) arg, &LP_IRQ(minor), sizeof(int));
			break;
		case LPGETSTATUS:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
			    sizeof(int));
		    	if (retval)
		    		return retval;
			else {
				int status = LP_S(minor);
				memcpy_tofs((int *) arg, &status, sizeof(int));
			}
			break;
		case LPRESET:
			lp_reset(minor);
			break;
		case LPGETSTATS:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
			    sizeof(struct lp_stats));
		    	if (retval)
		    		return retval;
			else {
				memcpy_tofs((int *) arg, &LP_STAT(minor), sizeof(struct lp_stats));
				if (suser())
					memset(&LP_STAT(minor), 0, sizeof(struct lp_stats));
			}
			break;
 		case LPGETFLAGS:
 			retval = verify_area(VERIFY_WRITE, (void *) arg,
 			    sizeof(int));
 		    	if (retval)
 		    		return retval;
 			else {
 				int status = LP_F(minor);
				memcpy_tofs((int *) arg, &status, sizeof(int));
			}
			break;
		default:
			retval = -EINVAL;
	}
	return retval;
}