⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 con3215.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
 */static inline raw3215_info *raw3215_find_info(int irq) {	raw3215_info *raw;	int i;	for (i = 0; i < NR_3215; i++) {		raw = raw3215[i];		if (raw != NULL && raw->irq == irq &&		    (raw->flags & RAW3215_ACTIVE))			break;	}	return (i >= NR_3215) ? NULL : raw;}/* * Interrupt routine, called from Ingo's I/O layer */static void raw3215_irq(int irq, void *int_parm, struct pt_regs *regs){	raw3215_info *raw;	raw3215_req *req;	struct tty_struct *tty;	devstat_t *stat;        int cstat, dstat;	int count, slen;	stat = (devstat_t *) int_parm;	req = (raw3215_req *) stat->intparm;	cstat = stat->cstat;	dstat = stat->dstat;	if (cstat != 0) {		raw = raw3215_find_info(irq);		if (raw != NULL) {			raw->message = KERN_WARNING				"Got nonzero channel status in raw3215_irq "				"(dev %i, dev sts 0x%2x, sch sts 0x%2x)";			raw->msg_dstat = dstat;			raw->msg_cstat = cstat;                        raw3215_sched_bh(raw);		}	}        if (dstat & 0x01) { /* we got a unit exception */		dstat &= ~0x01;  /* we can ignore it */        }	switch (dstat) {	case 0x80:		if (cstat != 0)			break;		/* Attention interrupt, someone hit the enter key */		if ((raw = raw3215_find_info(irq)) == NULL)			return;              /* That shouldn't happen ... */		/* Setup a read request */		raw3215_mk_read_req(raw);                if (MACHINE_IS_P390)                        memset(raw->inbuf, 0, RAW3215_INBUF_SIZE);                raw3215_sched_bh(raw);		break;	case 0x08:	case 0x0C:		/* Channel end interrupt. */		if ((raw = req->info) == NULL)                        return;              /* That shouldn't happen ... */		if (req->type == RAW3215_READ) {			/* store residual count, then wait for device end */			req->residual = stat->rescnt;		}		if (dstat == 0x08)			break;	case 0x04:		/* Device end interrupt. */                if ((raw = req->info) == NULL)                        return;              /* That shouldn't happen ... */		if (req->type == RAW3215_READ && raw->tty != NULL) {			char *cchar;			tty = raw->tty;                        count = 160 - req->residual;                        if (MACHINE_IS_P390) {                                slen = strnlen(raw->inbuf, RAW3215_INBUF_SIZE);                                if (count > slen)                                        count = slen;                        } else			if (count >= TTY_FLIPBUF_SIZE - tty->flip.count)				count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;			EBCASC(raw->inbuf, count);			if ((cchar = ctrlchar_handle(raw->inbuf, count, tty))) {				if (cchar == (char *)-1)					goto in_out;				tty->flip.count++;				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;				*tty->flip.char_buf_ptr++ = *cchar;				tty_flip_buffer_push(raw->tty);			} else {				memcpy(tty->flip.char_buf_ptr,				       raw->inbuf, count);				if (count < 2 ||				    (strncmp(raw->inbuf+count-2, "^n", 2) ||				    strncmp(raw->inbuf+count-2, "\252n", 2)) ) {					/* don't add the auto \n */					tty->flip.char_buf_ptr[count] = '\n';					memset(tty->flip.flag_buf_ptr,					       TTY_NORMAL, count + 1);					count++;				} else					count-=2;				tty->flip.char_buf_ptr += count;				tty->flip.flag_buf_ptr += count;				tty->flip.count += count;				tty_flip_buffer_push(raw->tty);			}		} else if (req->type == RAW3215_WRITE) {			raw->count -= req->len;                        raw->written -= req->len;		} in_out:		raw->flags &= ~RAW3215_WORKING;		raw3215_free_req(req);		/* check for empty wait */		if (waitqueue_active(&raw->empty_wait) &&		    raw->queued_write == NULL &&		    raw->queued_read == NULL) {			wake_up_interruptible(&raw->empty_wait);		}                raw3215_sched_bh(raw);		break;	default:		/* Strange interrupt, I'll do my best to clean up */                if ((raw = raw3215_find_info(irq)) == NULL)                        return;              /* That shouldn't happen ... */                if (raw == NULL) break;		if (req != NULL && req->type != RAW3215_FREE) {		        if (req->type == RAW3215_WRITE) {			        raw->count -= req->len;                                raw->written -= req->len;                        }                        raw->flags &= ~RAW3215_WORKING;                        raw3215_free_req(req);		}		raw->message = KERN_WARNING			"Spurious interrupt in in raw3215_irq "			"(dev %i, dev sts 0x%2x, sch sts 0x%2x)";		raw->msg_dstat = dstat;		raw->msg_cstat = cstat;                raw3215_sched_bh(raw);	}	return;}/* * Wait until length bytes are available int the output buffer. * Has to be called with the s390irq lock held. Can be called * disabled. */void raw3215_make_room(raw3215_info *raw, unsigned int length){	while (RAW3215_BUFFER_SIZE - raw->count < length) {		/* there might be a request pending */		raw->flags |= RAW3215_FLUSHING;		raw3215_mk_write_req(raw);		raw3215_try_io(raw);		raw->flags &= ~RAW3215_FLUSHING;		if (wait_cons_dev(raw->irq) != 0) {			/* that shouldn't happen */			raw->count = 0;			raw->written = 0;		}		/* Enough room freed up ? */		if (RAW3215_BUFFER_SIZE - raw->count >= length)			break;		/* there might be another cpu waiting for the lock */		s390irq_spin_unlock(raw->irq);		udelay(100);		s390irq_spin_lock(raw->irq);	}}/* * String write routine for 3215 devices */static intraw3215_write(raw3215_info *raw, const char *str,	      int from_user, unsigned int length){	unsigned long flags;	int ret, c;	int count;		ret = 0;	while (length > 0) {		s390irq_spin_lock_irqsave(raw->irq, flags);		count = (length > RAW3215_BUFFER_SIZE) ?					     RAW3215_BUFFER_SIZE : length;		length -= count;                raw3215_make_room(raw, count);		/* copy string to output buffer and convert it to EBCDIC */		if (from_user) {			while (1) {				c = MIN(count,					MIN(RAW3215_BUFFER_SIZE - raw->count,					    RAW3215_BUFFER_SIZE - raw->head));				if (c <= 0)					break;				c -= copy_from_user(raw->buffer + raw->head,						    str, c);				if (c == 0) {					if (!ret)						ret = -EFAULT;					break;				}				ASCEBC(raw->buffer + raw->head, c);				raw->head = (raw->head + c) &					    (RAW3215_BUFFER_SIZE - 1);				raw->count += c;				raw->line_pos += c;				str += c;				count -= c;				ret += c;			}		} else {			while (1) {				c = MIN(count,					MIN(RAW3215_BUFFER_SIZE - raw->count,					    RAW3215_BUFFER_SIZE - raw->head));				if (c <= 0)					break;				memcpy(raw->buffer + raw->head, str, c);				ASCEBC(raw->buffer + raw->head, c);				raw->head = (raw->head + c) &					    (RAW3215_BUFFER_SIZE - 1);				raw->count += c;				raw->line_pos += c;				str += c;				count -= c;				ret += c;			}		}                if (!(raw->flags & RAW3215_WORKING)) {                        raw3215_mk_write_req(raw);		        /* start or queue request */		        raw3215_try_io(raw);                }		s390irq_spin_unlock_irqrestore(raw->irq, flags);	}	return ret;}/* * Put character routine for 3215 devices */	static void raw3215_putchar(raw3215_info *raw, unsigned char ch){	unsigned long flags;        unsigned int length, i;	s390irq_spin_lock_irqsave(raw->irq, flags);	if (ch == '\t') {		length = TAB_STOP_SIZE - (raw->line_pos%TAB_STOP_SIZE);		raw->line_pos += length;		ch = ' ';        } else if (ch == '\n') {		length = 1;		raw->line_pos = 0;	} else {		length = 1;		raw->line_pos++;	}        raw3215_make_room(raw, length);	for (i = 0; i < length; i++) {		raw->buffer[raw->head] = (char) _ascebc[(int) ch];		raw->head = (raw->head + 1) & (RAW3215_BUFFER_SIZE - 1);		raw->count++;	}        if (!(raw->flags & RAW3215_WORKING)) {                raw3215_mk_write_req(raw);	        /* start or queue request */	        raw3215_try_io(raw);        }	s390irq_spin_unlock_irqrestore(raw->irq, flags);}/* * Flush routine, it simply sets the flush flag and tries to start  * pending IO. */static void raw3215_flush_buffer(raw3215_info *raw){	unsigned long flags;	s390irq_spin_lock_irqsave(raw->irq, flags);	if (raw->count > 0) {		raw->flags |= RAW3215_FLUSHING;		raw3215_try_io(raw);		raw->flags &= ~RAW3215_FLUSHING;	}	s390irq_spin_unlock_irqrestore(raw->irq, flags);}/* * Fire up a 3215 device. */static int raw3215_startup(raw3215_info *raw){	unsigned long flags;	if (raw->flags & RAW3215_ACTIVE)		return 0;	if (request_irq(raw->irq, raw3215_irq, SA_INTERRUPT,			"3215 terminal driver", &raw->devstat) != 0)		return -1;	raw->line_pos = 0;	raw->flags |= RAW3215_ACTIVE;	s390irq_spin_lock_irqsave(raw->irq, flags);        set_cons_dev(raw->irq);	raw3215_try_io(raw);	s390irq_spin_unlock_irqrestore(raw->irq, flags);	return 0;	}/* * Shutdown a 3215 device. */static void raw3215_shutdown(raw3215_info *raw){        DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED))		return;	/* Wait for outstanding requests, then free irq */	s390irq_spin_lock_irqsave(raw->irq, flags);	if ((raw->flags & RAW3215_WORKING) ||	    raw->queued_write != NULL ||	    raw->queued_read != NULL) {		raw->flags |= RAW3215_CLOSING;		add_wait_queue(&raw->empty_wait, &wait);		current->state = TASK_INTERRUPTIBLE;                s390irq_spin_unlock_irqrestore(raw->irq, flags);		schedule();		s390irq_spin_lock_irqsave(raw->irq, flags);		remove_wait_queue(&raw->empty_wait, &wait);                current->state = TASK_RUNNING;		raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING);	}	free_irq(raw->irq, NULL);	s390irq_spin_unlock_irqrestore(raw->irq, flags);}static intraw3215_find_dev(int number){	s390_dev_info_t dinfo;	int irq;	int count;	irq = get_irq_first();	count = 0;        while (count <= number && irq != -ENODEV) {                if (get_dev_info(irq, &dinfo) == -ENODEV)                        break;                if (dinfo.devno == console_device ||                    dinfo.sid_data.cu_type == 0x3215) {                        count++;                    if (count > number)                        return irq;                }                irq = get_irq_next(irq);        }        return -1;            /* console not found */}#ifdef CONFIG_TN3215_CONSOLE/* * Write a string to the 3215 console */static voidcon3215_write(struct console *co, const char *str, unsigned int count){	raw3215_info *raw;	int i;	if (count <= 0)		return;        raw = raw3215[0];       /* console 3215 is the first one */        while (count > 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -