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

📄 esp.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		sti();		for (i = 0; i < space_avail - 1; i += 2) {			outw(*((unsigned short *)(pio_buf->data + i)),			     info->port + UART_ESI_TX);		}		if (space_avail & 0x0001)			serial_out(info, UART_ESI_TX,				   pio_buf->data[space_avail - 1]);		cli();		if (info->xmit_cnt) {			serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);			serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);			space_avail = serial_in(info, UART_ESI_STAT1) << 8;			space_avail |= serial_in(info, UART_ESI_STAT2);			if (space_avail > info->xmit_cnt)				space_avail = info->xmit_cnt;		}	}	if (info->xmit_cnt < WAKEUP_CHARS) {		rs_sched_event(info, ESP_EVENT_WRITE_WAKEUP);#ifdef SERIAL_DEBUG_INTR		printk("THRE...");#endif		if (info->xmit_cnt <= 0) {			info->IER &= ~UART_IER_THRI;			serial_out(info, UART_ESI_CMD1,				   ESI_SET_SRV_MASK);			serial_out(info, UART_ESI_CMD2, info->IER);		}	}	release_pio_buffer(pio_buf);}static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int num_bytes){	unsigned long flags;		dma_bytes = num_bytes;	if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) {		memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]),		       dma_bytes);	} else {		int i = ESP_XMIT_SIZE - info->xmit_tail;		memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]),			i);		memcpy(&(dma_buffer[i]), info->xmit_buf, dma_bytes - i);	}	info->xmit_cnt -= dma_bytes;	info->xmit_tail = (info->xmit_tail + dma_bytes) & (ESP_XMIT_SIZE - 1);	if (info->xmit_cnt < WAKEUP_CHARS) {		rs_sched_event(info, ESP_EVENT_WRITE_WAKEUP);#ifdef SERIAL_DEBUG_INTR		printk("THRE...");#endif		if (info->xmit_cnt <= 0) {			info->IER &= ~UART_IER_THRI;			serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);			serial_out(info, UART_ESI_CMD2, info->IER);		}	}	info->stat_flags |= ESP_STAT_DMA_TX;		flags=claim_dma_lock();        disable_dma(dma);        clear_dma_ff(dma);        set_dma_mode(dma, DMA_MODE_WRITE);        set_dma_addr(dma, virt_to_bus(dma_buffer));        set_dma_count(dma, dma_bytes);        enable_dma(dma);        release_dma_lock(flags);                serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);}static _INLINE_ void transmit_chars_dma_done(struct esp_struct *info){	int num_bytes;	unsigned long flags;		flags=claim_dma_lock();	disable_dma(dma);	clear_dma_ff(dma);	num_bytes = dma_bytes - get_dma_residue(dma);	info->icount.tx += dma_bytes;	release_dma_lock(flags);	if (dma_bytes != num_bytes) {		dma_bytes -= num_bytes;		memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes);				flags=claim_dma_lock();        	disable_dma(dma);        	clear_dma_ff(dma);        	set_dma_mode(dma, DMA_MODE_WRITE);        	set_dma_addr(dma, virt_to_bus(dma_buffer));        	set_dma_count(dma, dma_bytes);        	enable_dma(dma);        	release_dma_lock(flags);        	        	serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);	} else {		dma_bytes = 0;		info->stat_flags &= ~ESP_STAT_DMA_TX;	}}static _INLINE_ void check_modem_status(struct esp_struct *info){	int	status;		serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);	status = serial_in(info, UART_ESI_STAT2);	if (status & UART_MSR_ANY_DELTA) {		/* update input line counters */		if (status & UART_MSR_TERI)			info->icount.rng++;		if (status & UART_MSR_DDSR)			info->icount.dsr++;		if (status & UART_MSR_DDCD)			info->icount.dcd++;		if (status & UART_MSR_DCTS)			info->icount.cts++;		wake_up_interruptible(&info->delta_msr_wait);	}	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))		printk("ttys%d CD now %s...", info->line,		       (status & UART_MSR_DCD) ? "on" : "off");#endif				if (status & UART_MSR_DCD)			wake_up_interruptible(&info->open_wait);		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&			   (info->flags & ASYNC_CALLOUT_NOHUP))) {#ifdef SERIAL_DEBUG_OPEN			printk("scheduling hangup...");#endif			MOD_INC_USE_COUNT;			if (schedule_task(&info->tqueue_hangup) == 0)				MOD_DEC_USE_COUNT;		}	}}/* * This is the serial driver's interrupt routine */static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs){	struct esp_struct * info;	unsigned err_status;	unsigned int scratch;#ifdef SERIAL_DEBUG_INTR	printk("rs_interrupt_single(%d)...", irq);#endif	info = (struct esp_struct *)dev_id;	err_status = 0;	scratch = serial_in(info, UART_ESI_SID);	cli();		if (!info->tty) {		sti();		return;	}	if (scratch & 0x04) { /* error */		serial_out(info, UART_ESI_CMD1, ESI_GET_ERR_STAT);		err_status = serial_in(info, UART_ESI_STAT1);		serial_in(info, UART_ESI_STAT2);		if (err_status & 0x01)			info->stat_flags |= ESP_STAT_RX_TIMEOUT;		if (err_status & 0x20) /* UART status */			check_modem_status(info);		if (err_status & 0x80) /* Start break */			wake_up_interruptible(&info->break_wait);	}			if ((scratch & 0x88) || /* DMA completed or timed out */	    (err_status & 0x1c) /* receive error */) {		if (info->stat_flags & ESP_STAT_DMA_RX)			receive_chars_dma_done(info, err_status);		else if (info->stat_flags & ESP_STAT_DMA_TX)			transmit_chars_dma_done(info);	}	if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) &&	    ((scratch & 0x01) || (info->stat_flags & ESP_STAT_RX_TIMEOUT)) &&	    (info->IER & UART_IER_RDI)) {		int num_bytes;		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);		serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL);		num_bytes = serial_in(info, UART_ESI_STAT1) << 8;		num_bytes |= serial_in(info, UART_ESI_STAT2);		if (num_bytes > (TTY_FLIPBUF_SIZE - info->tty->flip.count))		  num_bytes = TTY_FLIPBUF_SIZE - info->tty->flip.count;		if (num_bytes) {			if (dma_bytes ||			    (info->stat_flags & ESP_STAT_USE_PIO) ||			    (num_bytes <= info->config.pio_threshold))				receive_chars_pio(info, num_bytes);			else				receive_chars_dma(info, num_bytes);		}	}		if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) &&	    (scratch & 0x02) && (info->IER & UART_IER_THRI)) {		if ((info->xmit_cnt <= 0) || info->tty->stopped) {			info->IER &= ~UART_IER_THRI;			serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);			serial_out(info, UART_ESI_CMD2, info->IER);		} else {			int num_bytes;			serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);			serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);			num_bytes = serial_in(info, UART_ESI_STAT1) << 8;			num_bytes |= serial_in(info, UART_ESI_STAT2);			if (num_bytes > info->xmit_cnt)				num_bytes = info->xmit_cnt;			if (num_bytes) {				if (dma_bytes ||				    (info->stat_flags & ESP_STAT_USE_PIO) ||				    (num_bytes <= info->config.pio_threshold))					transmit_chars_pio(info, num_bytes);				else					transmit_chars_dma(info, num_bytes);			}		}	}	info->last_active = jiffies;#ifdef SERIAL_DEBUG_INTR	printk("end.\n");#endif	sti();}/* * ------------------------------------------------------------------- * Here ends the serial interrupt routines. * ------------------------------------------------------------------- *//* * This routine is used to handle the "bottom half" processing for the * serial driver, known also the "software interrupt" processing. * This processing is done at the kernel interrupt level, after the * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This * is where time-consuming activities which can not be done in the * interrupt driver proper are done; the interrupt driver schedules * them using rs_sched_event(), and they get done here. */static void do_serial_bh(void){	run_task_queue(&tq_esp);}static void do_softint(void *private_){	struct esp_struct	*info = (struct esp_struct *) private_;	struct tty_struct	*tty;		tty = info->tty;	if (!tty)		return;	if (test_and_clear_bit(ESP_EVENT_WRITE_WAKEUP, &info->event)) {		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		    tty->ldisc.write_wakeup)			(tty->ldisc.write_wakeup)(tty);		wake_up_interruptible(&tty->write_wait);	}}/* * This routine is called from the scheduler tqueue when the interrupt * routine has signalled that a hangup has occurred.  The path of * hangup processing is: * * 	serial interrupt routine -> (scheduler tqueue) -> * 	do_serial_hangup() -> tty->hangup() -> esp_hangup() *  */static void do_serial_hangup(void *private_){	struct esp_struct	*info = (struct esp_struct *) private_;	struct tty_struct	*tty;		tty = info->tty;	if (tty)		tty_hangup(tty);	MOD_DEC_USE_COUNT;}/* * --------------------------------------------------------------- * Low level utility subroutines for the serial driver:  routines to * figure out the appropriate timeout for an interrupt chain, routines * to initialize and startup a serial port, and routines to shutdown a * serial port.  Useful stuff like that. * --------------------------------------------------------------- */static _INLINE_ void esp_basic_init(struct esp_struct * info){	/* put ESPC in enhanced mode */	serial_out(info, UART_ESI_CMD1, ESI_SET_MODE);		if (info->stat_flags & ESP_STAT_NEVER_DMA)		serial_out(info, UART_ESI_CMD2, 0x01);	else		serial_out(info, UART_ESI_CMD2, 0x31);	/* disable interrupts for now */	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);	serial_out(info, UART_ESI_CMD2, 0x00);	/* set interrupt and DMA channel */	serial_out(info, UART_ESI_CMD1, ESI_SET_IRQ);	if (info->stat_flags & ESP_STAT_NEVER_DMA)		serial_out(info, UART_ESI_CMD2, 0x01);	else		serial_out(info, UART_ESI_CMD2, (dma << 4) | 0x01);	serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ);	if (info->line % 8)	/* secondary port */		serial_out(info, UART_ESI_CMD2, 0x0d);	/* shared */	else if (info->irq == 9)		serial_out(info, UART_ESI_CMD2, 0x02);	else		serial_out(info, UART_ESI_CMD2, info->irq);	/* set error status mask (check this) */	serial_out(info, UART_ESI_CMD1, ESI_SET_ERR_MASK);	if (info->stat_flags & ESP_STAT_NEVER_DMA)		serial_out(info, UART_ESI_CMD2, 0xa1);	else		serial_out(info, UART_ESI_CMD2, 0xbd);	serial_out(info, UART_ESI_CMD2, 0x00);	/* set DMA timeout */	serial_out(info, UART_ESI_CMD1, ESI_SET_DMA_TMOUT);	serial_out(info, UART_ESI_CMD2, 0xff);	/* set FIFO trigger levels */	serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER);	serial_out(info, UART_ESI_CMD2, info->config.rx_trigger >> 8);	serial_out(info, UART_ESI_CMD2, info->config.rx_trigger);	serial_out(info, UART_ESI_CMD2, info->config.tx_trigger >> 8);	serial_out(info, UART_ESI_CMD2, info->config.tx_trigger);	/* Set clock scaling and wait states */	serial_out(info, UART_ESI_CMD1, ESI_SET_PRESCALAR);	serial_out(info, UART_ESI_CMD2, 0x04 | ESPC_SCALE);	/* set reinterrupt pacing */	serial_out(info, UART_ESI_CMD1, ESI_SET_REINTR);	serial_out(info, UART_ESI_CMD2, 0xff);}static int startup(struct esp_struct * info){	unsigned long flags;	int	retval=0;        unsigned int num_chars;	save_flags(flags); cli();	if (info->flags & ASYNC_INITIALIZED)		goto out;	if (!info->xmit_buf) {		info->xmit_buf = (unsigned char *)get_free_page(GFP_KERNEL);		retval = -ENOMEM;		if (!info->xmit_buf)			goto out;	}#ifdef SERIAL_DEBUG_OPEN	printk("starting up ttys%d (irq %d)...", info->line, info->irq);#endif	/* Flush the RX buffer.  Using the ESI flush command may cause */	/* wild interrupts, so read all the data instead. */	serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);	serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL);	num_chars = serial_in(info, UART_ESI_STAT1) << 8;	num_chars |= serial_in(info, UART_ESI_STAT2);	while (num_chars > 1) {		inw(info->port + UART_ESI_RX);		num_chars -= 2;	}	if (num_chars)		serial_in(info, UART_ESI_RX);	/* set receive character timeout */	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);	serial_out(info, UART_ESI_CMD2, info->config.rx_timeout);	/* clear all flags except the "never DMA" flag */	info->stat_flags &= ESP_STAT_NEVER_DMA;	if (info->stat_flags & ESP_STAT_NEVER_DMA)		info->stat_flags |= ESP_STAT_USE_PIO;	/*	 * Allocate the IRQ	 */	retval = request_irq(info->irq, rs_interrupt_single, SA_SHIRQ,			     "esp serial", info);	if (retval) {		if (capable(CAP_SYS_ADMIN)) {			if (info->tty)				set_bit(TTY_IO_ERROR,					&info->tty->flags);			retval = 0;		}		goto out;	}	if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) {		dma_buffer = (char *)__get_dma_pages(			GFP_KERNEL, get_order(DMA_BUFFER_SZ));		/* use PIO mode if DMA buf/chan cannot be allocated */		if (!dma_buffer)			info->stat_flags |= ESP_STAT_USE_PIO;		else if (request_dma(dma, "esp serial")) {			free_pages((unsigned long)dma_buffer,				   get_order(DMA_BUFFER_SZ));			dma_buffer = 0;			info->stat_flags |= ESP_STAT_USE_PIO;		}				}	info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);	serial_out(info, UART_ESI_CMD2, UART_MCR);	serial_out(info, UART_ESI_CMD2, info->MCR);		/*	 * Finally, enable interrupts	 */	/* info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; */	info->IER = UART_IER_RLSI | UART_IER_RDI | UART_IER_DMA_TMOUT |			UART_IER_DMA_TC;	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);	serial_out(info, UART_ESI_CMD2, info->IER);		if (info->tty)		clear_bit(TTY_IO_ERROR, &info->tty->flags);

⌨️ 快捷键说明

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