Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Aug 2003 23:57:21 -0700 (PDT)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 36647 for review
Message-ID:  <200308220657.h7M6vLc3071728@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=36647

Change 36647 by marcel@marcel_nfs on 2003/08/21 23:56:39

	Rough implementation of the sab82532 driver for bus access.
	This allows us to boot single- and multi-user. Lacking are:
	o  reading and writing modem/line signals
	o  flushing of the transmitter/receiver

Affected files ...

.. //depot/projects/uart/dev/uart/uart_dev_sab82532.c#10 edit

Differences ...

==== //depot/projects/uart/dev/uart/uart_dev_sab82532.c#10 (text+ko) ====

@@ -180,7 +180,7 @@
 sab82532_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
     int parity)
 {
-	uint8_t pvr;
+	uint8_t ccr0, pvr;
 
 	if (bas->rclk == 0)
 		bas->rclk = DEFAULT_RCLK;
@@ -188,18 +188,61 @@
 	/* Set all pins, except DTR pins to be inputs. */
 	uart_setreg(bas, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B));
 	uart_barrier(bas);
-	/* Disable port interrupts */
+	/* Disable port interrupts. */
 	uart_setreg(bas, SAB_PIM, 0xff);
 	uart_barrier(bas);
 	/* Interrupts are active low. */
 	uart_setreg(bas, SAB_IPC, SAB_IPC_ICPL);
 	uart_barrier(bas);
+	/* Set DTR. */
+	pvr = uart_getreg(bas, SAB_PVR);
+	pvr |= IS_CHANNEL_A(bas) ? SAB_PVR_DTR_A : SAB_PVR_DTR_B;
+	uart_setreg(bas, SAB_PVR, pvr);
+	uart_barrier(bas);
+
+	/* power down */
+	uart_setreg(bas, SAB_CCR0, 0);
+	uart_barrier(bas);
+
+	/* set basic configuration */
+	ccr0 = SAB_CCR0_MCE|SAB_CCR0_SC_NRZ|SAB_CCR0_SM_ASYNC;
+	uart_setreg(bas, SAB_CCR0, ccr0);
+	uart_barrier(bas);
+	uart_setreg(bas, SAB_CCR1, SAB_CCR1_ODS|SAB_CCR1_BCR|SAB_CCR1_CM_7);
+	uart_barrier(bas);
+	uart_setreg(bas, SAB_CCR2, SAB_CCR2_BDF|SAB_CCR2_SSEL|SAB_CCR2_TOE);
+	uart_barrier(bas);
+	uart_setreg(bas, SAB_CCR3, 0);
+	uart_barrier(bas);
+	uart_setreg(bas, SAB_CCR4, SAB_CCR4_MCK4|SAB_CCR4_EBRG);
+	uart_barrier(bas);
+	uart_setreg(bas, SAB_MODE, SAB_MODE_RTS|SAB_MODE_FCTS|SAB_MODE_RAC);
+	uart_barrier(bas);
+	uart_setreg(bas, SAB_RFC, SAB_RFC_DPS|SAB_RFC_RFDF|
+	    SAB_RFC_RFTH_32CHAR);
+	uart_barrier(bas);
 
+	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+		;
+	uart_setreg(bas, SAB_CMDR, SAB_CMDR_XRES);
+	uart_barrier(bas);
+	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+		;
+	uart_setreg(bas, SAB_CMDR, SAB_CMDR_RRES);
+	uart_barrier(bas);
+
 	sab82532_param(bas, baudrate, databits, stopbits, parity);
 
-	pvr = uart_getreg(bas, SAB_PVR);
-	pvr |= IS_CHANNEL_A(bas) ? SAB_PVR_DTR_A : SAB_PVR_DTR_B;
-	uart_setreg(bas, SAB_PVR, pvr);
+	/* Clear interrupts. */
+	uart_setreg(bas, SAB_IMR0, 0xff);
+	uart_setreg(bas, SAB_IMR1, 0xff);
+	uart_barrier(bas);
+	uart_getreg(bas, SAB_ISR0);
+	uart_getreg(bas, SAB_ISR1);
+	uart_barrier(bas);
+
+	/* Power up. */
+	uart_setreg(bas, SAB_CCR0, ccr0|SAB_CCR0_PU);
 	uart_barrier(bas);
 }
 
@@ -250,8 +293,8 @@
 
 	while (!(uart_getreg(bas, SAB_STAR) & SAB_STAR_RFNE))
 		DELAY(delay);
-	while ((uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC))
-		DELAY(delay);
+	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+		;
 
 	uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD);
 	uart_barrier(bas);
@@ -263,9 +306,8 @@
 	uart_barrier(bas);
 
 	/* Blow away everything left in the FIFO... */
-	while ((uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC))
-		DELAY(delay);
-
+	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+		;
 	uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC);
 	uart_barrier(bas);
 	return (c);
@@ -318,10 +360,16 @@
 	struct uart_bas *bas;
 
 	bas = &sc->sc_bas;
-
 	if (!sc->sc_console && !sc->sc_dbgport)
 		sab82532_init(bas, 9600, 8, 1, UART_PARITY_NONE);
 
+	sc->sc_rxfifosz = 32;
+	sc->sc_txfifosz = 32;
+
+	uart_setreg(bas, SAB_IMR0, SAB_IMR0_PERR|SAB_IMR0_FERR|SAB_IMR0_PLLA);
+	uart_setreg(bas, SAB_IMR1, SAB_IMR1_BRK|SAB_IMR1_XDU|SAB_IMR1_TIN|
+	    SAB_IMR1_XMR|SAB_IMR1_XPR);
+	uart_barrier(bas);
 	return (0);
 }
 
@@ -331,9 +379,14 @@
 	struct uart_bas *bas;
 
 	bas = &sc->sc_bas;
-
-	uart_setreg(bas, SAB_IPC, SAB_IPC_ICPL | SAB_IPC_VIS);
-	uart_setreg(bas, SAB_RFC, uart_getreg(bas, SAB_RFC) & ~SAB_RFC_RFDF);
+	uart_setreg(bas, SAB_IMR0, 0xff);
+	uart_setreg(bas, SAB_IMR1, 0xff);
+	uart_barrier(bas);
+	uart_getreg(bas, SAB_ISR0);
+	uart_getreg(bas, SAB_ISR1);
+	uart_barrier(bas);
+	uart_setreg(bas, SAB_CCR0, 0);
+	uart_barrier(bas);
 	return (0);
 }
 
@@ -354,8 +407,35 @@
 static int
 sab82532_bus_ipend(struct uart_softc *sc)
 {
+	struct uart_bas *bas;
+	int ipend;
+	uint8_t isr0, isr1;
 
-	return (0);
+	bas = &sc->sc_bas;
+	isr0 = uart_getreg(bas, SAB_ISR0);
+	isr1 = uart_getreg(bas, SAB_ISR1);
+	uart_barrier(bas);
+
+	if (isr0 & SAB_ISR0_TIME) {
+		while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+			;
+		uart_setreg(bas, SAB_CMDR, SAB_CMDR_RFRD);
+		uart_barrier(bas);
+	}
+
+	ipend = 0;
+	if (isr1 & SAB_ISR1_BRKT)
+		ipend |= UART_IPEND_BREAK;
+	if (isr0 & SAB_ISR0_RFO)
+		ipend |= UART_IPEND_OVERRUN;
+	if (isr0 & (SAB_ISR0_TCD|SAB_ISR0_RPF))
+		ipend |= UART_IPEND_RXREADY;
+	if ((isr0 & SAB_ISR0_CDSC) || (isr1 & SAB_ISR1_CSC))
+		ipend |= UART_IPEND_SIGCHG;
+	if (isr1 & SAB_ISR1_ALLS)
+		ipend |= UART_IPEND_TXIDLE;
+
+	return (ipend);
 }
 
 static int
@@ -397,7 +477,36 @@
 static int
 sab82532_bus_receive(struct uart_softc *sc)
 {
+	struct uart_bas *bas;
+	int count, xc;
+	uint8_t s;
 
+	bas = &sc->sc_bas;
+	count = uart_getreg(bas, SAB_RBCL) & 31;
+	if (count == 0)
+		count = 32;
+	while (count && !uart_rx_full(sc)) {
+		xc = uart_getreg(bas, SAB_RFIFO);
+		s = uart_getreg(bas, SAB_RFIFO);
+		if (s & SAB_RSTAT_FE)
+			xc |= UART_STAT_FRAMERR;
+		if (s & SAB_RSTAT_PE)
+			xc |= UART_STAT_PARERR;
+		uart_rx_put(sc, xc);
+		count -= 2;
+	}
+	/*
+	 * Oops, we couldn't get all data from the FIFO. Mark an overflow
+	 * condition and let upper layers deal with this. We need to free
+	 * the Rx FIFO. Sorry...
+	 */
+	if (count)
+		sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+
+	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+		;
+	uart_setreg(bas, SAB_CMDR, SAB_CMDR_RMC);
+	uart_barrier(bas);
 	return (0);
 }
 
@@ -411,6 +520,16 @@
 static int
 sab82532_bus_transmit(struct uart_softc *sc)
 {
+	struct uart_bas *bas;
+	int i;
 
+	bas = &sc->sc_bas;
+	for (i = 0; i < sc->sc_txdatasz; i++)
+		uart_setreg(bas, SAB_XFIFO + i, sc->sc_txbuf[i]);
+	uart_barrier(bas);
+	while (uart_getreg(bas, SAB_STAR) & SAB_STAR_CEC)
+		;
+	uart_setreg(bas, SAB_CMDR, SAB_CMDR_XF);
+	sc->sc_txbusy = 1;
 	return (0);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200308220657.h7M6vLc3071728>