Exemplo n.º 1
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;
}
Exemplo n.º 2
0
static inline int lp_write_interrupt(unsigned int minor, const char * buf, int count)
{
	unsigned long copy_size;
	unsigned long total_bytes_written = 0;
	unsigned long bytes_written;
	struct lp_struct *lp = &lp_table[minor];
	unsigned char status;

	do {
		bytes_written = 0;
		copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
		memcpy_fromfs(lp->lp_buffer, buf, copy_size);

		while (copy_size) {
			if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {
				--copy_size;
				++bytes_written;
				lp_table[minor].runchars++;
			} else {
				int rc = total_bytes_written + bytes_written;
				if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
					 LP_STAT(minor).maxrun = lp_table[minor].runchars;
				status = LP_S(minor);
				if ((status & LP_POUTPA)) {
					printk(KERN_INFO "lp%d out of paper\n", minor);
					if (LP_F(minor) & LP_ABORT)
						return rc?rc:-ENOSPC;
				} else if (!(status & LP_PSELECD)) {
					printk(KERN_INFO "lp%d off-line\n", minor);
					if (LP_F(minor) & LP_ABORT)
						return rc?rc:-EIO;
				} else if (!(status & LP_PERRORP)) {
					printk(KERN_ERR "lp%d printer error\n", minor);
					if (LP_F(minor) & LP_ABORT)
						return rc?rc:-EIO;
				}
				LP_STAT(minor).sleeps++;
				cli();
				outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
				status = LP_S(minor);
				if ((!(status & LP_PACK) || (status & LP_PBUSY))
				  && LP_CAREFUL_READY(minor, status)) {
					outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
					sti();
					continue;
				}
				lp_table[minor].runchars=0;
				current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
				interruptible_sleep_on(&lp->lp_wait_q);
				outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
				sti();
				if (current->signal & ~current->blocked) {
					if (total_bytes_written + bytes_written)
						return total_bytes_written + bytes_written;
					else
						return -EINTR;
				}
			}
		}

		total_bytes_written += bytes_written;
		buf += bytes_written;
		count -= bytes_written;

	} while (count > 0);

	return total_bytes_written;
}