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

📄 mxser.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)					i = 16;		/* 57600 bps */				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)					i = 17;		/* 115200 bps */#ifdef ASYNC_SPD_SHI				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)					i = 18;#endif#ifdef ASYNC_SPD_WARP				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)					i = 19;#endif			}			if (mxvar_baud_table[i] == 134) {				quot = (2 * info->baud_base / 269);			} else if (mxvar_baud_table[i]) {				quot = info->baud_base / mxvar_baud_table[i];				if (quot == 0)					quot = 1;			} else {				quot = 0;			}		} else if (quot == 0)			quot = 1;	} else {		quot = 0;	}	if (quot) {		info->MCR |= UART_MCR_DTR;		save_flags(flags);		cli();		outb(info->MCR, info->base + UART_MCR);		restore_flags(flags);	} else {		info->MCR &= ~UART_MCR_DTR;		save_flags(flags);		cli();		outb(info->MCR, info->base + UART_MCR);		restore_flags(flags);		return ret;	}	/* byte size and parity */	switch (cflag & CSIZE) {	case CS5:		cval = 0x00;		break;	case CS6:		cval = 0x01;		break;	case CS7:		cval = 0x02;		break;	case CS8:		cval = 0x03;		break;	default:		cval = 0x00;		break;		/* too keep GCC shut... */	}	if (cflag & CSTOPB)		cval |= 0x04;	if (cflag & PARENB)		cval |= UART_LCR_PARITY;	if (!(cflag & PARODD))		cval |= UART_LCR_EPAR;	if ((info->type == PORT_8250) || (info->type == PORT_16450)) {		fcr = 0;	} else {		fcr = UART_FCR_ENABLE_FIFO;		switch (info->rx_trigger) {		case 1:			fcr |= UART_FCR_TRIGGER_1;			break;		case 4:			fcr |= UART_FCR_TRIGGER_4;			break;		case 8:			fcr |= UART_FCR_TRIGGER_8;			break;		default:			fcr |= UART_FCR_TRIGGER_14;		}	}	/* CTS flow control flag and modem status interrupts */	info->IER &= ~UART_IER_MSI;	info->MCR &= ~UART_MCR_AFE;	if (cflag & CRTSCTS) {		info->flags |= ASYNC_CTS_FLOW;		info->IER |= UART_IER_MSI;		if (info->type == PORT_16550A)			info->MCR |= UART_MCR_AFE;	} else {		info->flags &= ~ASYNC_CTS_FLOW;	}	outb(info->MCR, info->base + UART_MCR);	if (cflag & CLOCAL)		info->flags &= ~ASYNC_CHECK_CD;	else {		info->flags |= ASYNC_CHECK_CD;		info->IER |= UART_IER_MSI;	}	outb(info->IER, info->base + UART_IER);	/*	 * Set up parity check flag	 */	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;	if (I_INPCK(info->tty))		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))		info->read_status_mask |= UART_LSR_BI;	info->ignore_status_mask = 0;#if 0	/* This should be safe, but for some broken bits of hardware... */	if (I_IGNPAR(info->tty)) {		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;		info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;	}#endif	if (I_IGNBRK(info->tty)) {		info->ignore_status_mask |= UART_LSR_BI;		info->read_status_mask |= UART_LSR_BI;		/*		 * If we're ignore parity and break indicators, ignore		 * overruns too.  (For real raw support).		 */		if (I_IGNPAR(info->tty)) {			info->ignore_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;			info->read_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;		}	}	save_flags(flags);	cli();	outb(cval | UART_LCR_DLAB, info->base + UART_LCR);	/* set DLAB */	outb(quot & 0xff, info->base + UART_DLL);	/* LS of divisor */	outb(quot >> 8, info->base + UART_DLM);		/* MS of divisor */	outb(cval, info->base + UART_LCR);	/* reset DLAB */	outb(fcr, info->base + UART_FCR);	/* set fcr */	restore_flags(flags);	return ret;}/* * ------------------------------------------------------------ * friends of mxser_ioctl() * ------------------------------------------------------------ */static int mxser_get_serial_info(struct mxser_struct *info,				 struct serial_struct *retinfo){	struct serial_struct tmp;	if (!retinfo)		return (-EFAULT);	memset(&tmp, 0, sizeof(tmp));	tmp.type = info->type;	tmp.line = info->port;	tmp.port = info->base;	tmp.irq = info->irq;	tmp.flags = info->flags;	tmp.baud_base = info->baud_base;	tmp.close_delay = info->close_delay;	tmp.closing_wait = info->closing_wait;	tmp.custom_divisor = info->custom_divisor;	tmp.hub6 = 0;	copy_to_user(retinfo, &tmp, sizeof(*retinfo));	return (0);}static int mxser_set_serial_info(struct mxser_struct *info,				 struct serial_struct *new_info){	struct serial_struct new_serial;	unsigned int flags;	int retval = 0;	if (!new_info || !info->base)		return (-EFAULT);	copy_from_user(&new_serial, new_info, sizeof(new_serial));	if ((new_serial.irq != info->irq) ||	    (new_serial.port != info->base) ||	    (new_serial.type != info->type) ||	    (new_serial.custom_divisor != info->custom_divisor) ||	    (new_serial.baud_base != info->baud_base))		return (-EPERM);	flags = info->flags & ASYNC_SPD_MASK;	if (!suser()) {		if ((new_serial.baud_base != info->baud_base) ||		    (new_serial.close_delay != info->close_delay) ||		    ((new_serial.flags & ~ASYNC_USR_MASK) !=		     (info->flags & ~ASYNC_USR_MASK)))			return (-EPERM);		info->flags = ((info->flags & ~ASYNC_USR_MASK) |			       (new_serial.flags & ASYNC_USR_MASK));	} else {		/*		 * OK, past this point, all the error checking has been done.		 * At this point, we start making changes.....		 */		info->flags = ((info->flags & ~ASYNC_FLAGS) |			       (new_serial.flags & ASYNC_FLAGS));		info->close_delay = new_serial.close_delay * HZ / 100;		info->closing_wait = new_serial.closing_wait * HZ / 100;	}	if (info->flags & ASYNC_INITIALIZED) {		if (flags != (info->flags & ASYNC_SPD_MASK)) {			mxser_change_speed(info, 0);		}	} else		retval = mxser_startup(info);	return (retval);}/* * mxser_get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically *          is emptied.  On bus types like RS485, the transmitter must *          release the bus after transmitting. This must be done when *          the transmit shift register is empty, not be done when the *          transmit holding register is empty.  This functionality *          allows an RS485 driver to be written in user space. */static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int *value){	unsigned char status;	unsigned int result;	unsigned long flags;	save_flags(flags);	cli();	status = inb(info->base + UART_LSR);	restore_flags(flags);	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);	put_user(result, value);	return (0);}/* * This routine sends a break character out the serial port. */static void mxser_send_break(struct mxser_struct *info, int duration){	unsigned long flags;	if (!info->base)		return;	current->state = TASK_INTERRUPTIBLE;	save_flags(flags);	cli();	outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);	schedule_timeout(duration);	outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);	restore_flags(flags);}static int mxser_get_modem_info(struct mxser_struct *info,				unsigned int *value){	unsigned char control, status;	unsigned int result;	unsigned long flags;	control = info->MCR;	save_flags(flags);	cli();	status = inb(info->base + UART_MSR);	if (status & UART_MSR_ANY_DELTA)		mxser_check_modem_status(info, status);	restore_flags(flags);	result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |	    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |	    ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |	    ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |	    ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |	    ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);	put_user(result, value);	return (0);}static int mxser_set_modem_info(struct mxser_struct *info, unsigned int cmd,				unsigned int *value){	unsigned int arg;	unsigned long flags;	if(get_user(arg, value))		return -EFAULT;	switch (cmd) {	case TIOCMBIS:		if (arg & TIOCM_RTS)			info->MCR |= UART_MCR_RTS;		if (arg & TIOCM_DTR)			info->MCR |= UART_MCR_DTR;		break;	case TIOCMBIC:		if (arg & TIOCM_RTS)			info->MCR &= ~UART_MCR_RTS;		if (arg & TIOCM_DTR)			info->MCR &= ~UART_MCR_DTR;		break;	case TIOCMSET:		info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |			     ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |			     ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));		break;	default:		return (-EINVAL);	}	save_flags(flags);	cli();	outb(info->MCR, info->base + UART_MCR);	restore_flags(flags);	return (0);}static int mxser_read_register(int, unsigned short *);static int mxser_program_mode(int);static void mxser_normal_mode(int);static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf){	int id, i, bits;	unsigned short regs[16], irq;	unsigned char scratch, scratch2;	id = mxser_read_register(cap, regs);	if (id == C168_ASIC_ID)		hwconf->board_type = MXSER_BOARD_C168_ISA;	else if (id == C104_ASIC_ID)		hwconf->board_type = MXSER_BOARD_C104_ISA;	else if (id == CI104J_ASIC_ID)		hwconf->board_type = MXSER_BOARD_CI104J;	else		return (0);	irq = regs[9] & 0x0F;	irq = irq | (irq << 4);	irq = irq | (irq << 8);	if ((irq != regs[9]) || ((id == 1) && (irq != regs[10]))) {		return (MXSER_ERR_IRQ_CONFLIT);	}	if (!irq) {		return (MXSER_ERR_IRQ);	}	for (i = 0; i < 8; i++)		hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8;	hwconf->irq = (int) (irq & 0x0F);	if ((regs[12] & 0x80) == 0) {		return (MXSER_ERR_VECTOR);	}	hwconf->vector = (int) regs[11];	/* interrupt vector */	if (id == 1)		hwconf->vector_mask = 0x00FF;	else		hwconf->vector_mask = 0x000F;	for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {		if (regs[12] & bits)			hwconf->baud_base[i] = 921600;		else			hwconf->baud_base[i] = 115200;	}	scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);	outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);	outb(0, cap + UART_EFR);	/* EFR is the same as FCR */	outb(scratch2, cap + UART_LCR);	outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);	scratch = inb(cap + UART_IIR);	if (scratch & 0xC0)		hwconf->uart_type = PORT_16550A;	else		hwconf->uart_type = PORT_16450;	if (id == 1)		hwconf->ports = 8;	else		hwconf->ports = 4;	return (hwconf->ports);}#define CHIP_SK 	0x01	/* Serial Data Clock  in Eprom */#define CHIP_DO 	0x02	/* Serial Data Output in Eprom */#define CHIP_CS 	0x04	/* Serial Chip Select in Eprom */#define CHIP_DI 	0x08	/* Serial Data Input  in Eprom */#define EN_CCMD 	0x000	/* Chip's command register     */#define EN0_RSARLO	0x008	/* Remote start address reg 0  */#define EN0_RSARHI	0x009	/* Remote start address reg 1  */#define EN0_RCNTLO	0x00A	/* Remote byte count reg WR    */#define EN0_RCNTHI	0x00B	/* Remote byte count reg WR    */#define EN0_DCFG	0x00E	/* Data configuration reg WR   */#define EN0_PORT	0x010	/* Rcv missed frame error counter RD */#define ENC_PAGE0	0x000	/* Select page 0 of chip registers   */#define ENC_PAGE3	0x0C0	/* Select page 3 of chip registers   */static int mxser_read_register(int port, unsigned short *regs){	int i, k, value, id;	unsigned int j;	id = mxser_program_mode(port);	if (id < 0)		return (id);	for (i = 0; i < 14; i++) {		k = (i & 0x3F) | 0x180;		for (j = 0x100; j > 0; j >>= 1) {			outb(CHIP_CS, port);			if (k & j) {				outb(CHIP_CS | CHIP_DO, port);				outb(CHIP_CS | CHIP_DO | CHIP_SK, port);	/* A? bit of read */			} else {				outb(CHIP_CS, port);				outb(CHIP_CS | CHIP_SK, port);	/* A? bit of read */			}		}		(void) inb(port);		value = 0;		for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {			outb(CHIP_CS, port);			outb(CHIP_CS | CHIP_SK, port);			if (inb(port) & CHIP_DI)				value |= j;		}		regs[i] = value;		outb(0, port);	}	mxser_normal_mode(port);	return (id);}static int mxser_program_mode(int port){	int id, i, j, n;	unsigned long flags;	save_flags(flags);	cli();	outb(0, port);	outb(0, port);	outb(0, port);	(void) inb(port);	(void) inb(port);	outb(0, port);	(void) inb(port);	restore_flags(flags);	id = inb(port + 1) & 0x1F;	if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID))		return (-1);	for (i = 0, j = 0; i < 4; i++) {		n = inb(port + 2);		if (n == 'M') {			j = 1;		} else if ((j == 1) && (n == 1)) {			j = 2;			break;		} else			j = 0;	}	if (j != 2)		id = -2;	return (id);}static void mxser_normal_mode(int port){	int i, n;	outb(0xA5, port + 1);	outb(0x80, port + 3);	outb(12, port + 0);	/* 9600 bps */	outb(0, port + 1);	outb(0x03, port + 3);	/* 8 data bits */	outb(0x13, port + 4);	/* loop back mode */	for (i = 0; i < 16; i++) {		n = inb(port + 5);		if ((n & 0x61) == 0x60)			break;		if ((n & 1) == 1)			(void) inb(port);	}	outb(0x00, port + 4);}

⌨️ 快捷键说明

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