patch-2.4.5 linux/arch/cris/drivers/serial.c

Next file: linux/arch/cris/drivers/serial.h
Previous file: linux/arch/cris/drivers/parport.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.4/linux/arch/cris/drivers/serial.c linux/arch/cris/drivers/serial.c
@@ -1,4 +1,4 @@
-/* $Id: serial.c,v 1.10 2001/03/05 13:14:07 bjornw Exp $
+/* $Id: serial.c,v 1.12 2001/04/19 12:23:07 bjornw Exp $
  *
  * Serial port driver for the ETRAX 100LX chip
  *
@@ -7,6 +7,15 @@
  *      Many, many authors. Based once upon a time on serial.c for 16x50.
  *
  * $Log: serial.c,v $
+ * Revision 1.12  2001/04/19 12:23:07  bjornw
+ * CONFIG_RS485 -> CONFIG_ETRAX_RS485
+ *
+ * Revision 1.11  2001/04/05 14:29:48  markusl
+ * Updated according to review remarks i.e.
+ * -Use correct types in port structure to avoid compiler warnings
+ * -Try to use IO_* macros whenever possible
+ * -Open should never return -EBUSY
+ *
  * Revision 1.10  2001/03/05 13:14:07  bjornw
  * Another spelling fix
  *
@@ -190,7 +199,7 @@
  *
  */
 
-static char *serial_version = "$Revision: 1.10 $";
+static char *serial_version = "$Revision: 1.12 $";
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -299,6 +308,18 @@
 #define REG_BAUD 3
 #define REG_XOFF 4  /* this is a 32 bit register */
 
+/*
+ * General note regarding the use of IO_* macros in this file: 
+ *
+ * We will use the bits defined for DMA channel 6 when using various
+ * IO_* macros (e.g. IO_STATE, IO_MASK, IO_EXTRACT) and _assume_ they are
+ * the same for all channels (which of course they are).
+ *
+ * We will also use the bits defined for serial port 0 when writing commands
+ * to the different ports, as these bits too are the same for all ports.
+ */
+
+
 /* this is the data for the four serial ports in the etrax100 */
 /*  DMA2(ser2), DMA4(ser3), DMA6(ser0) or DMA8(ser1) */
 /* R_DMA_CHx_CLR_INTR, R_DMA_CHx_FIRST, R_DMA_CHx_CMD */
@@ -343,9 +364,9 @@
 
 
 /* RS-485 */
-#if defined(CONFIG_RS485)
-#if defined(CONFIG_RS485_ON_PA)
-static int rs485_pa_bit = CONFIG_RS485_ON_PA_BIT;
+#if defined(CONFIG_ETRAX_RS485)
+#if defined(CONFIG_ETRAX_RS485_ON_PA)
+static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT;
 #endif
 #endif
   
@@ -421,8 +442,8 @@
   }
 };
 
-#if defined(CONFIG_RS485) && defined(CONFIG_RS485_ON_PA)
-unsigned char rs485_pa_port = CONFIG_RS485_ON_PA_BIT;
+#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_RS485_ON_PA)
+unsigned char rs485_pa_port = CONFIG_ETRAX_RS485_ON_PA_BIT;
 #endif
 
 #define E100_RTS_MASK 0x20
@@ -668,7 +689,8 @@
 {
 #ifndef CONFIG_SVINTO_SIM
 	/* disable the receiver */
-	info->port[REG_REC_CTRL] = (info->rx_ctrl &= ~0x40);
+	info->port[REG_REC_CTRL] = info->rx_ctrl &=
+		~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable);
 #endif
 }
 
@@ -677,7 +699,8 @@
 {
 #ifndef CONFIG_SVINTO_SIM
 	/* enable the receiver */
-	info->port[REG_REC_CTRL] = (info->rx_ctrl |= 0x40);
+	info->port[REG_REC_CTRL] = info->rx_ctrl |=
+		IO_MASK(R_SERIAL0_REC_CTRL, rec_enable);
 #endif
 }
 
@@ -747,14 +770,14 @@
 }
 #endif
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 /* Enable RS-485 mode on selected port. This is UGLY. */
 static int
 e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r)
 {
 	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
 
-#if defined(CONFIG_RS485_ON_PA)	
+#if defined(CONFIG_ETRAX_RS485_ON_PA)	
 	*R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit);
 #endif
 
@@ -766,7 +789,6 @@
 	return 0;
 }
 
-/* Enable RS-485 mode on selected port. This is UGLY. */
 static int
 e100_write_rs485(struct tty_struct *tty,struct rs485_write *r)
 {
@@ -782,7 +804,7 @@
 	 * the receiver before initiating a DMA transfer
 	 */
 	e100_rts(info, info->rs485.rts_on_send);
-#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
 	e100_disable_rx(info);
 	e100_disable_rxdma_irq(info);
 #endif
@@ -824,14 +846,16 @@
 	max_j = jiffies + (delay_ms * HZ)/1000 + 10;
 
 	while (jiffies < max_j ) {
-	  if (info->port[REG_STATUS] & 0x20) {
+	  if (info->port[REG_STATUS] &
+	      IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
 	    for( i=0 ; i<100; i++ ) {};
-	    if (info->port[REG_STATUS] & 0x20) {
+	    if (info->port[REG_STATUS] &
+		IO_STATE(R_SERIAL0_STATUS, tr_ready, ready)) {
 	      /* ~25 for loops per usec */
-	      stop_delay = 25 * (1000000 / info->baud);
+	      stop_delay = 1000000 / info->baud;
 	      if(cflags & CSTOPB) 
 		stop_delay *= 2;
-	      for( i=0 ; i<stop_delay; i++ ) {};
+	      udelay(stop_delay);
 	      break;
 	    }
 	  }
@@ -839,7 +863,7 @@
 
 	e100_rts(info, info->rs485.rts_after_sent);
 	
-#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
 	e100_enable_rx(info);
 	e100_enable_rxdma_irq(info);
 #endif
@@ -942,7 +966,9 @@
 	return;
 #endif
 	/* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
-	*info->oclrintradr = 3;
+	*info->oclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
 
 #ifdef SERIAL_DEBUG_INTR
 	if(info->line == SERIAL_DEBUG_LINE)
@@ -987,19 +1013,20 @@
 		/* our job here is done, don't schedule any new DMA transfer */
 		info->tr_running = 0;
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 		/* Check if we should toggle RTS now */
 		if (info->rs485.enabled)
 		{
 			/* Make sure fifo is empty */
 			int in_fifo = 0 ;
 			do{
-				in_fifo = (*info->ostatusadr) & 0x007F ;
+				in_fifo = IO_EXTRACT(R_DMA_CH6_STATUS, avail,
+						    *info->ostatusadr);
 			}  while (in_fifo > 0) ;
 			/* Any way to really check transmitter empty? (TEMT) */
 			/* Control RTS to set to RX mode */
 			e100_rts(info, info->rs485.rts_after_sent); 
-#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER)
 			e100_enable_rx(info);
 			e100_enable_rxdma_irq(info);
 #endif
@@ -1060,7 +1087,9 @@
 
 	/* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
 
-	*info->iclrintradr = 3;
+	*info->iclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
 
 	if(!tty) /* something wrong... */
 		return;
@@ -1088,7 +1117,9 @@
 		/* read the status register so we can detect errors */
 		rstat = info->port[REG_STATUS];
 
-		if(rstat & 0xe) {
+		if(rstat & (IO_MASK(R_SERIAL0_STATUS, overrun) |
+			    IO_MASK(R_SERIAL0_STATUS, par_err) |
+			    IO_MASK(R_SERIAL0_STATUS, framing_err))) {
 			/* if we got an error, we must reset it by reading the
 			 * data_in field
 			 */
@@ -1148,7 +1179,7 @@
 	descr->status = 0;
 
 	*info->ifirstadr = virt_to_phys(descr);
-	*info->icmdadr = 1; /* start */
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
 
 #ifdef SERIAL_HANDLE_EARLY_ERRORS
 	e100_enable_serial_data_irq(info);
@@ -1170,8 +1201,9 @@
 
 	/* reset the input dma channel to be sure it works */
 	
-	*info->icmdadr = 4;
-	while((*info->icmdadr & 7) == 4);
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+	while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+	      IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
 
 	descr = &info->rec_descr;
 	
@@ -1186,7 +1218,8 @@
 	info->tty->flip.count = 0;
 
 	*info->ifirstadr = virt_to_phys(descr);
-	*info->icmdadr = 1; /* start */
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start);
+	
 }
 
 
@@ -1293,7 +1326,7 @@
 static struct timer_list flush_timer;
 
 static void 
-timed_flush_handler(void)
+timed_flush_handler(unsigned long ptr)
 {
 	struct e100_serial *info;
 	int i;
@@ -1381,7 +1414,7 @@
 				PROCSTAT(early_errors_cnt[info->line]++);
 
 				/* restart the DMA */
-				*info->icmdadr = 3;
+				*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
 			} 
 			else { /* it was a valid byte, now let the dma do the rest */
 #ifdef SERIAL_DEBUG_INTR
@@ -1472,7 +1505,7 @@
 	if (info->flags & ASYNC_INITIALIZED) {
 		free_page(page);
 		restore_flags(flags);
-		return -EBUSY;
+		return 0;
 	}
 	
 	if (info->xmit.buf)
@@ -1518,14 +1551,22 @@
 	 * Reset the DMA channels and make sure their interrupts are cleared
 	 */
 	
-	*info->icmdadr = 4; /* reset command */
-	*info->ocmdadr = 4; /* reset command */
-	
-	while((*info->icmdadr & 7) == 4); /* wait until reset cycle is complete */
-	while((*info->ocmdadr & 7) == 4);
-	
-	*info->iclrintradr = 3; /* make sure the irqs are cleared */
-	*info->oclrintradr = 3;
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+	*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+
+	/* wait until reset cycle is complete */
+	while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) ==
+	      IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+
+	while(IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) ==
+	      IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset));
+	
+	*info->iclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
+	*info->oclrintradr =
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) |
+		IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do);
 	
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1597,8 +1638,8 @@
 
 	/* reset both dma channels */
 
-	*info->icmdadr = 4;
-	*info->ocmdadr = 4;
+	*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
+	*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset);
 
 #endif /* CONFIG_SVINTO_SIM */
 
@@ -1658,42 +1699,51 @@
 #ifndef CONFIG_SVINTO_SIM
 	info->port[REG_BAUD] = cflag_to_etrax_baud(cflag);
 	/* start with default settings and then fill in changes */
-	
-	info->rx_ctrl &= ~(0x07); /* 8 bit, no/even parity */
-	info->tx_ctrl &= ~(0x37); /* 8 bit, no/even parity, 1 stop bit, no cts */
+
+	/* 8 bit, no/even parity */
+	info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) |
+			   IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) |
+			   IO_MASK(R_SERIAL0_REC_CTRL, rec_par));
+
+	/* 8 bit, no/even parity, 1 stop bit, no cts */
+	info->tx_ctrl &= ~(IO_MASK(R_SERIAL0_TR_CTRL, tr_bitnr) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, tr_par_en) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, tr_par) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, stop_bits) |
+			   IO_MASK(R_SERIAL0_TR_CTRL, auto_cts));
 	
 	if ((cflag & CSIZE) == CS7) {
 		/* set 7 bit mode */
-		info->tx_ctrl |= 0x01;
-		info->rx_ctrl |= 0x01;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit);
+		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit);
 	}
 	
 	if (cflag & CSTOPB) {
 		/* set 2 stop bit mode */
-		info->tx_ctrl |= 0x10;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, stop_bits, two_bits);
 	}	  
 	
 	if (cflag & PARENB) {
 		/* enable parity */
-		info->tx_ctrl |= 0x02;
-		info->rx_ctrl |= 0x02;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable);
+		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable);
 	}
 	
 	if (cflag & PARODD) {
 		/* set odd parity */
-		info->tx_ctrl |= 0x04;
-		info->rx_ctrl |= 0x04;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd);
+		info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd);
 	}
 	
 	if (cflag & CRTSCTS) {
 		/* enable automatic CTS handling */
-		info->tx_ctrl |= 0x20;
+		info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, active);
 	}
 	
 	/* make sure the tx and rx are enabled */
 	
-	info->tx_ctrl |= 0x40;
-	info->rx_ctrl |= 0x40;
+	info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable);
+	info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
 
 	/* actually write the control regs to the hardware */
 	
@@ -2330,7 +2380,7 @@
 				return -EFAULT;
 			return 0;
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 		case TIOCSERSETRS485:
 			error = verify_area(VERIFY_WRITE, (void *) arg,
 					sizeof(struct rs485_control));
@@ -2488,10 +2538,10 @@
 
 	/* port closed */
 
-#if defined(CONFIG_RS485)
+#if defined(CONFIG_ETRAX_RS485)
 	if (info->rs485.enabled) {
 		info->rs485.enabled = 0;
-#if defined(CONFIG_RS485_ON_PA)
+#if defined(CONFIG_ETRAX_RS485_ON_PA)
 		*R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit);
 #endif
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)