亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? lp.c

?? LINUX1.0源代碼,代碼條理清晰
?? C
字號:
/*
 * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
 * Copyright (C) 1992,1993 by Michael K. Johnson
 * - Thanks much to Gunter Windau for pointing out to me where the error
 *   checking ought to be.
 * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
 */

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
#include <linux/lp.h>
#include <linux/malloc.h>

#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>

/* 
 * All my debugging code assumes that you debug with only one printer at
 * a time. RWWH
 */

#undef LP_DEBUG

static int lp_reset(int minor)
{
	int testvalue;
	unsigned char command;

	command = LP_PSELECP | LP_PINITP;

	/* reset value */
	outb_p(0, LP_C(minor));
	for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
		;
	outb_p(command, LP_C(minor));
	return LP_S(minor);
}

#ifdef LP_DEBUG
static int lp_max_count = 1;
#endif

static int lp_char_polled(char lpchar, int minor)
{
	int status = 0, wait = 0;
	unsigned long count  = 0; 

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

	if (count == LP_CHAR(minor)) {
		return 0;
		/* we timed out, and the character was /not/ printed */
	}
#ifdef LP_DEBUG
	if (count > lp_max_count) {
		printk("lp success after %d counts.\n",count);
		lp_max_count=count;
	}
#endif
	outb_p(lpchar, LP_B(minor));
	/* 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 )));

	return 1;
}

static int lp_char_interrupt(char lpchar, int minor)
{
	int wait = 0;
	unsigned char status;


	if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) {

		outb_p(lpchar, LP_B(minor));
		/* 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 )));
		return 1;
	}

	return 0;
}

#ifdef LP_DEBUG
	unsigned int lp_total_chars = 0;
	unsigned int lp_last_call = 0;
#endif

static void lp_interrupt(int irq)
{
	struct lp_struct *lp = &lp_table[0];
	struct lp_struct *lp_end = &lp_table[LP_NO];

	while (irq != lp->irq) {
		if (++lp >= lp_end)
			return;
	}

	wake_up(&lp->lp_wait_q);
}

static int lp_write_interrupt(struct inode * inode, struct file * file, char * buf, int count)
{
	unsigned int minor = MINOR(inode->i_rdev);
	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;
			} else {
				if (!((status = LP_S(minor)) & LP_PERRORP)) {
					int rc = total_bytes_written + bytes_written;

					if ((status & LP_POUTPA)) {
						printk("lp%d out of paper\n", minor);
						if (!rc)
							rc = -ENOSPC;
					} else if (!(status & LP_PSELECD)) {
						printk("lp%d off-line\n", minor);
						if (!rc)
							rc = -EIO;
					} else {
						printk("lp%d printer error\n", minor);
						if (!rc)
							rc = -EIO;
					}
					if(LP_F(minor) & LP_ABORT)
						return rc;
				}
				cli();
				outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
				status = LP_S(minor);
				if (!(status & LP_PACK) || (status & LP_PBUSY)) {
					outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
					sti();
					continue;
				}
				current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
				interruptible_sleep_on(&lp->lp_wait_q);
				outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
				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;
}

static int lp_write_polled(struct inode * inode, struct file * file,
			   char * buf, int count)
{
	int  retval;
	unsigned int minor = MINOR(inode->i_rdev);
	char c, *temp = buf;

#ifdef LP_DEBUG
	if (jiffies-lp_last_call > LP_TIME(minor)) {
		lp_total_chars = 0;
		lp_max_count = 1;
	}
	lp_last_call = jiffies;
#endif

	temp = buf;
	while (count > 0) {
		c = get_fs_byte(temp);
		retval = lp_char_polled(c, minor);
		/* only update counting vars if character was printed */
		if (retval) { count--; temp++;
#ifdef LP_DEBUG
			lp_total_chars++;
#endif
		}
		if (!retval) { /* if printer timed out */
			int status = LP_S(minor);

			if (status & LP_POUTPA) {
				printk("lp%d out of paper\n", minor);
				if(LP_F(minor) & LP_ABORT)
					return temp-buf?temp-buf:-ENOSPC;
				current->state = TASK_INTERRUPTIBLE;
				current->timeout = jiffies + LP_TIMEOUT_POLLED;
				schedule();
			} else
			if (!(status & LP_PSELECD)) {
				printk("lp%d off-line\n", minor);
				if(LP_F(minor) & LP_ABORT)
					return temp-buf?temp-buf:-EIO;
				current->state = TASK_INTERRUPTIBLE;
				current->timeout = jiffies + LP_TIMEOUT_POLLED;
				schedule();
			} else
	                /* not offline or out of paper. on fire? */
			if (!(status & LP_PERRORP)) {
				printk("lp%d on fire\n", minor);
				if(LP_F(minor) & LP_ABORT)
					return temp-buf?temp-buf:-EFAULT;
				current->state = TASK_INTERRUPTIBLE;
				current->timeout = jiffies + LP_TIMEOUT_POLLED;
				schedule();
			}

			/* check for signals before going to sleep */
			if (current->signal & ~current->blocked) {
				if (temp != buf)
					return temp-buf;
				else
					return -EINTR;
			}
#ifdef LP_DEBUG
			printk("lp sleeping at %d characters for %d jiffies\n",
				lp_total_chars, LP_TIME(minor));
			lp_total_chars=0;
#endif
			current->state = TASK_INTERRUPTIBLE;
			current->timeout = jiffies + LP_TIME(minor);
			schedule();
		}
	}
	return temp-buf;
}

static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
{
	if (LP_IRQ(MINOR(inode->i_rdev)))
		return lp_write_interrupt(inode, file, buf, count);
	else
		return lp_write_polled(inode, file, buf, count);
}

static int lp_lseek(struct inode * inode, struct file * file,
		    off_t offset, int origin)
{
	return -ESPIPE;
}

static int lp_open(struct inode * inode, struct file * file)
{
	unsigned int minor = MINOR(inode->i_rdev);
	int ret;
	unsigned int irq;
	struct sigaction sa;

	if (minor >= LP_NO)
		return -ENODEV;
	if ((LP_F(minor) & LP_EXIST) == 0)
		return -ENODEV;
	if (LP_F(minor) & LP_BUSY)
		return -EBUSY;

	if ((irq = LP_IRQ(minor))) {
		lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
		if (!lp_table[minor].lp_buffer)
			return -ENOMEM;

		sa.sa_handler = lp_interrupt;
		sa.sa_flags = SA_INTERRUPT;
		sa.sa_mask = 0;
		sa.sa_restorer = NULL;
		ret = irqaction(irq, &sa);
		if (ret) {
			kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
			lp_table[minor].lp_buffer = NULL;
			printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret);
			return ret;
		}
	}

	LP_F(minor) |= LP_BUSY;

	return 0;
}

static void lp_release(struct inode * inode, struct file * file)
{
	unsigned int minor = MINOR(inode->i_rdev);
	unsigned int irq;

	if ((irq = LP_IRQ(minor))) {
		free_irq(irq);
		kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
		lp_table[minor].lp_buffer = NULL;
	}

	LP_F(minor) &= ~LP_BUSY;
}


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("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;
			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 LPWAIT:
			LP_WAIT(minor) = arg;
			break;
		case LPSETIRQ: {
			int oldirq;
			int newirq = arg;
			struct lp_struct *lp = &lp_table[minor];
			struct sigaction sa;

			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);
			}
			if (newirq) {
				/* Install new irq */
				sa.sa_handler = lp_interrupt;
				sa.sa_flags = SA_INTERRUPT;
				sa.sa_mask = 0;
				sa.sa_restorer = NULL;
				if ((retval = irqaction(newirq, &sa))) {
					if (oldirq) {
						/* restore old irq */
						irqaction(oldirq, &sa);
					} 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 = LP_IRQ(minor);
			break;
		default:
			retval = -EINVAL;
	}
	return retval;
}


static struct file_operations lp_fops = {
	lp_lseek,
	NULL,		/* lp_read */
	lp_write,
	NULL,		/* lp_readdir */
	NULL,		/* lp_select */
	lp_ioctl,
	NULL,		/* lp_mmap */
	lp_open,
	lp_release
};

long lp_init(long kmem_start)
{
	int offset = 0;
	unsigned int testvalue = 0;
	int count = 0;

	if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
		printk("unable to get major %d for line printer\n", LP_MAJOR);
		return kmem_start;
	}
	/* take on all known port values */
	for (offset = 0; offset < LP_NO; offset++) {
		/* write to port & read back to check */
		outb_p( LP_DUMMY, LP_B(offset));
		for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
			;
		testvalue = inb_p(LP_B(offset));
		if (testvalue != 255) {
			LP_F(offset) |= LP_EXIST;
			lp_reset(offset);
			printk("lp_init: lp%d exists (%d), ", offset, testvalue);
			if (LP_IRQ(offset))
				printk("using IRQ%d\n", LP_IRQ(offset));
			else
				printk("using polling driver\n");
			count++;
		}
	}
	if (count == 0)
		printk("lp_init: no lp devices found\n");
	return kmem_start;
}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产精品久久久久久一区二区三区| 日韩午夜激情免费电影| 日韩理论片中文av| 色女孩综合影院| 夜夜操天天操亚洲| 欧美男人的天堂一二区| 日本aⅴ免费视频一区二区三区| 欧美一区二区三区播放老司机| 久久精品99国产精品| 久久久午夜精品理论片中文字幕| 成人自拍视频在线| 亚洲最大成人综合| 欧美一区二区福利在线| 国产盗摄一区二区| 亚洲色图视频网站| 91精品国产一区二区三区| 国产乱人伦精品一区二区在线观看| 国产精品久久久久久久久久久免费看 | 成人久久久精品乱码一区二区三区| 国产精品色在线| 欧洲av一区二区嗯嗯嗯啊| 久久99国产精品尤物| 国产精品素人视频| 欧美久久久久中文字幕| 国产精品一区二区久久不卡| 亚洲免费电影在线| 2024国产精品| 色狠狠色狠狠综合| 狠狠色丁香久久婷婷综合_中| 亚洲人成精品久久久久| 日韩视频免费观看高清完整版| 成人丝袜高跟foot| 日韩中文字幕区一区有砖一区 | 在线视频观看一区| 韩日精品视频一区| 亚洲成人tv网| 国产精品国产成人国产三级| 日韩丝袜情趣美女图片| 色婷婷av一区二区三区软件| 国产主播一区二区| 日韩在线一区二区| 一区二区三区精品| 欧美国产日本韩| 欧美丰满美乳xxx高潮www| 成人免费毛片a| 狠狠色丁香婷婷综合久久片| 天堂久久一区二区三区| 综合激情成人伊人| 国产亚洲午夜高清国产拍精品| 欧美三级在线看| 91麻豆免费在线观看| 国产.精品.日韩.另类.中文.在线.播放 | 色欧美88888久久久久久影院| 国产精品自拍网站| 毛片一区二区三区| 日韩二区三区在线观看| 亚洲一区二区三区自拍| 亚洲欧美日韩一区二区三区在线观看| 久久婷婷一区二区三区| 日韩一区二区视频| 337p亚洲精品色噜噜狠狠| 色视频一区二区| 色综合久久天天综合网| av成人免费在线| 成人av电影观看| 成人视屏免费看| 国产精品18久久久久久vr| 精品制服美女丁香| 久久国产精品色| 韩国精品一区二区| 乱中年女人伦av一区二区| 麻豆久久久久久| 久久超碰97中文字幕| 久久丁香综合五月国产三级网站| 亚洲mv大片欧洲mv大片精品| 亚洲国产aⅴ天堂久久| 亚洲午夜久久久| 五月开心婷婷久久| 肉色丝袜一区二区| 久久国产精品72免费观看| 国产专区综合网| 国产成人综合亚洲91猫咪| 国产91精品在线观看| 岛国精品一区二区| 色综合久久88色综合天天免费| 在线观看三级视频欧美| 欧美日韩免费视频| 日韩欧美一区中文| 久久亚洲捆绑美女| 国产精品嫩草影院com| 一区二区三区四区在线免费观看| 一区二区三区日韩在线观看| 亚洲1区2区3区4区| 免费成人在线视频观看| 国产另类ts人妖一区二区| 成人美女视频在线观看18| 在线观看亚洲a| 91精品国产91久久久久久一区二区| 日韩免费观看高清完整版| 国产日韩v精品一区二区| 亚洲欧美日韩国产一区二区三区 | 日韩在线a电影| 久久超碰97中文字幕| 成人免费的视频| 欧美曰成人黄网| 精品久久国产字幕高潮| 一区二区中文字幕在线| 午夜在线电影亚洲一区| 国产一本一道久久香蕉| 91在线免费看| 精品免费视频一区二区| 亚洲精品成人少妇| 麻豆精品久久久| 一本色道亚洲精品aⅴ| 日韩欧美视频一区| 亚洲欧洲性图库| 免费成人在线播放| 色综合天天视频在线观看| 欧美一区二区美女| 一色桃子久久精品亚洲| 精品一区二区影视| 欧美色图在线观看| 国产欧美日韩在线| 日韩激情视频网站| 色综合欧美在线视频区| 久久久国产精品不卡| 日韩中文字幕亚洲一区二区va在线 | 国产精品久久久一本精品| 日韩不卡一二三区| 在线观看日韩电影| 国产日韩影视精品| 日本亚洲欧美天堂免费| 在线中文字幕不卡| 欧美精彩视频一区二区三区| 久久国内精品自在自线400部| 在线看日本不卡| 国产精品久久久久9999吃药| 久久福利视频一区二区| 欧美猛男超大videosgay| 亚洲精品一二三| 成人aa视频在线观看| 国产午夜精品久久| 激情五月播播久久久精品| 欧美美女视频在线观看| 亚洲精品精品亚洲| 成人av在线一区二区| 久久久综合精品| 国精产品一区一区三区mba视频 | 欧美日韩亚洲国产综合| 亚洲天堂网中文字| 国产91精品在线观看| 久久青草欧美一区二区三区| 久久精品99国产精品| 欧美一区二区三区啪啪| 日本亚洲免费观看| 欧美一区二区三区视频免费| 亚洲成人动漫av| 欧美日韩午夜影院| 午夜视黄欧洲亚洲| 欧美一a一片一级一片| 亚洲一区二区精品3399| 日本乱码高清不卡字幕| 亚洲自拍都市欧美小说| 欧美亚洲综合久久| 亚洲国产aⅴ天堂久久| 欧美精品自拍偷拍动漫精品| 五月婷婷综合激情| 欧美色电影在线| 日韩中文字幕麻豆| 欧美成人女星排行榜| 精品系列免费在线观看| 久久嫩草精品久久久久| 国产精品伊人色| 中文天堂在线一区| 一本一本久久a久久精品综合麻豆 一本一道波多野结衣一区二区 | 国产精品99久久久久久似苏梦涵| 精品va天堂亚洲国产| 国产成人精品免费| 中文字幕在线观看一区| 欧美手机在线视频| 全国精品久久少妇| 久久综合九色综合97_久久久| 国产麻豆精品在线| 亚洲视频免费在线| 欧美三级韩国三级日本一级| 五月婷婷综合网| 久久影院午夜论| 不卡一区在线观看| 亚洲午夜激情av| 欧美成人精品3d动漫h| 丰满少妇久久久久久久| 亚洲综合一区二区三区| 日韩精品一区二区三区老鸭窝| 国产成人精品免费在线| 亚洲一区二区在线视频| 久久综合久久综合久久| 色哟哟精品一区| 久草这里只有精品视频| 亚洲精品欧美激情| 日韩欧美精品三级|