PERFORCE change 157143 for review

Hans Petter Selasky hselasky at FreeBSD.org
Wed Feb 4 08:22:29 PST 2009


http://perforce.freebsd.org/chv.cgi?CH=157143

Change 157143 by hselasky at hselasky_laptop001 on 2009/02/04 16:22:19

	
	USB serial: Simplify line state programming,
	reduce memory requirement.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb2/serial/usb2_serial.c#25 edit
.. //depot/projects/usb/src/sys/dev/usb2/serial/usb2_serial.h#14 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb2/serial/usb2_serial.c#25 (text+ko) ====

@@ -95,12 +95,7 @@
 static usb2_proc_callback_t usb2_com_cfg_start_transfers;
 static usb2_proc_callback_t usb2_com_cfg_open;
 static usb2_proc_callback_t usb2_com_cfg_close;
-static usb2_proc_callback_t usb2_com_cfg_break_on;
-static usb2_proc_callback_t usb2_com_cfg_break_off;
-static usb2_proc_callback_t usb2_com_cfg_dtr_on;
-static usb2_proc_callback_t usb2_com_cfg_dtr_off;
-static usb2_proc_callback_t usb2_com_cfg_rts_on;
-static usb2_proc_callback_t usb2_com_cfg_rts_off;
+static usb2_proc_callback_t usb2_com_cfg_line_state;
 static usb2_proc_callback_t usb2_com_cfg_status_change;
 static usb2_proc_callback_t usb2_com_cfg_param;
 
@@ -543,6 +538,11 @@
 	sc->sc_msr = 0;
 	sc->sc_mcr = 0;
 
+	/* reset programmed line state */
+	sc->sc_pls_curr = 0;
+	sc->sc_pls_set = 0;
+	sc->sc_pls_clr = 0;
+
 	usb2_com_queue_command(sc, usb2_com_cfg_open, NULL,
 	    &sc->sc_open_task[0].hdr,
 	    &sc->sc_open_task[1].hdr);
@@ -703,165 +703,119 @@
 }
 
 static void
-usb2_com_cfg_break_on(struct usb2_proc_msg *_task)
+usb2_com_cfg_line_state(struct usb2_proc_msg *_task)
 {
 	struct usb2_com_cfg_task *task = 
 	    (struct usb2_com_cfg_task *)_task;
 	struct usb2_com_softc *sc = task->sc;
+	uint8_t notch_bits;
+	uint8_t any_bits;
+	uint8_t prev_value;
+	uint8_t last_value;
+	uint8_t mask;
 
 	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
 		return;
 	}
-	DPRINTF("\n");
+
+	mask = 0;
+	/* compute callback mask */
+	if (sc->sc_callback->usb2_com_cfg_set_dtr)
+		mask |= UCOM_LS_DTR;
+	if (sc->sc_callback->usb2_com_cfg_set_rts)
+		mask |= UCOM_LS_RTS;
+	if (sc->sc_callback->usb2_com_cfg_set_break)
+		mask |= UCOM_LS_BREAK;
 
-	if (sc->sc_callback->usb2_com_cfg_set_break) {
-		(sc->sc_callback->usb2_com_cfg_set_break) (sc, 1);
-	}
-}
+	/* compute the bits we are to program */
+	notch_bits = (sc->sc_pls_set & sc->sc_pls_clr) & mask;
+	any_bits = (sc->sc_pls_set | sc->sc_pls_clr) & mask;
+	prev_value = sc->sc_pls_curr ^ notch_bits;
+	last_value = sc->sc_pls_curr;
 
-static void
-usb2_com_cfg_break_off(struct usb2_proc_msg *_task)
-{
-	struct usb2_com_cfg_task *task = 
-	    (struct usb2_com_cfg_task *)_task;
-	struct usb2_com_softc *sc = task->sc;
+	/* reset programmed line state */
+	sc->sc_pls_curr = 0;
+	sc->sc_pls_set = 0;
+	sc->sc_pls_clr = 0;
 
-	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
-		return;
-	}
-	DPRINTF("\n");
+	/* ensure that we don't loose any levels */
+	if (notch_bits & UCOM_LS_DTR)
+		sc->sc_callback->usb2_com_cfg_set_dtr(sc,
+		    (prev_value & UCOM_LS_DTR) ? 1 : 0);
+	if (notch_bits & UCOM_LS_RTS)
+		sc->sc_callback->usb2_com_cfg_set_rts(sc,
+		    (prev_value & UCOM_LS_RTS) ? 1 : 0);
+	if (notch_bits & UCOM_LS_BREAK)
+		sc->sc_callback->usb2_com_cfg_set_break(sc,
+		    (prev_value & UCOM_LS_BREAK) ? 1 : 0);
 
-	if (sc->sc_callback->usb2_com_cfg_set_break) {
-		(sc->sc_callback->usb2_com_cfg_set_break) (sc, 0);
-	}
+	/* set last value */
+	if (any_bits & UCOM_LS_DTR)
+		sc->sc_callback->usb2_com_cfg_set_dtr(sc,
+		    (last_value & UCOM_LS_DTR) ? 1 : 0);
+	if (any_bits & UCOM_LS_RTS)
+		sc->sc_callback->usb2_com_cfg_set_rts(sc,
+		    (last_value & UCOM_LS_RTS) ? 1 : 0);
+	if (any_bits & UCOM_LS_BREAK)
+		sc->sc_callback->usb2_com_cfg_set_break(sc,
+		    (last_value & UCOM_LS_BREAK) ? 1 : 0);
 }
 
 static void
-usb2_com_break(struct usb2_com_softc *sc, uint8_t onoff)
+usb2_com_line_state(struct usb2_com_softc *sc,
+    uint8_t set_bits, uint8_t clear_bits)
 {
 	mtx_assert(sc->sc_mtx, MA_OWNED);
 
 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
 		return;
 	}
-	DPRINTF("onoff = %d\n", onoff);
 
-	if (onoff)
-		usb2_com_queue_command(sc, usb2_com_cfg_break_on, NULL,
-		    &sc->sc_break_on_task[0].hdr, 
-		    &sc->sc_break_on_task[1].hdr);
-	else
-		usb2_com_queue_command(sc, usb2_com_cfg_break_off, NULL,
-		    &sc->sc_break_off_task[0].hdr, 
-		    &sc->sc_break_off_task[1].hdr);
-}
+	DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits);
 
-static void
-usb2_com_cfg_dtr_on(struct usb2_proc_msg *_task)
-{
-	struct usb2_com_cfg_task *task = 
-	    (struct usb2_com_cfg_task *)_task;
-	struct usb2_com_softc *sc = task->sc;
+	/* update current programmed line state */
+	sc->sc_pls_curr |= set_bits;
+	sc->sc_pls_curr &= ~clear_bits;
+	sc->sc_pls_set |= set_bits;
+	sc->sc_pls_clr |= clear_bits;
 
-	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
-		return;
-	}
-	DPRINTF("\n");
-
-	if (sc->sc_callback->usb2_com_cfg_set_dtr) {
-		(sc->sc_callback->usb2_com_cfg_set_dtr) (sc, 1);
-	}
+	/* defer driver programming */
+	usb2_com_queue_command(sc, usb2_com_cfg_line_state, NULL,
+	    &sc->sc_line_state_task[0].hdr, 
+	    &sc->sc_line_state_task[1].hdr);
 }
 
 static void
-usb2_com_cfg_dtr_off(struct usb2_proc_msg *_task)
+usb2_com_break(struct usb2_com_softc *sc, uint8_t onoff)
 {
-	struct usb2_com_cfg_task *task = 
-	    (struct usb2_com_cfg_task *)_task;
-	struct usb2_com_softc *sc = task->sc;
+	DPRINTF("onoff = %d\n", onoff);
 
-	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
-		return;
-	}
-	DPRINTF("\n");
-
-	if (sc->sc_callback->usb2_com_cfg_set_dtr) {
-		(sc->sc_callback->usb2_com_cfg_set_dtr) (sc, 0);
-	}
+	if (onoff)
+		usb2_com_line_state(sc, UCOM_LS_BREAK, 0);
+	else
+		usb2_com_line_state(sc, 0, UCOM_LS_BREAK);
 }
 
 static void
 usb2_com_dtr(struct usb2_com_softc *sc, uint8_t onoff)
 {
-	mtx_assert(sc->sc_mtx, MA_OWNED);
-
-	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
-		return;
-	}
 	DPRINTF("onoff = %d\n", onoff);
 
 	if (onoff)
-		usb2_com_queue_command(sc, usb2_com_cfg_dtr_on, NULL,
-		    &sc->sc_dtr_on_task[0].hdr,
-		    &sc->sc_dtr_on_task[1].hdr);
+		usb2_com_line_state(sc, UCOM_LS_DTR, 0);
 	else
-		usb2_com_queue_command(sc, usb2_com_cfg_dtr_off, NULL,
-		    &sc->sc_dtr_off_task[0].hdr,
-		    &sc->sc_dtr_off_task[1].hdr);
+		usb2_com_line_state(sc, 0, UCOM_LS_DTR);
 }
 
 static void
-usb2_com_cfg_rts_on(struct usb2_proc_msg *_task)
-{
-	struct usb2_com_cfg_task *task = 
-	    (struct usb2_com_cfg_task *)_task;
-	struct usb2_com_softc *sc = task->sc;
-
-	DPRINTF("\n");
-
-	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
-		return;
-	}
-	if (sc->sc_callback->usb2_com_cfg_set_rts) {
-		(sc->sc_callback->usb2_com_cfg_set_rts) (sc, 1);
-	}
-}
-
-static void
-usb2_com_cfg_rts_off(struct usb2_proc_msg *_task)
-{
-	struct usb2_com_cfg_task *task = 
-	    (struct usb2_com_cfg_task *)_task;
-	struct usb2_com_softc *sc = task->sc;
-
-	DPRINTF("\n");
-
-	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
-		return;
-	}
-	if (sc->sc_callback->usb2_com_cfg_set_rts) {
-		(sc->sc_callback->usb2_com_cfg_set_rts) (sc, 0);
-	}
-}
-
-static void
 usb2_com_rts(struct usb2_com_softc *sc, uint8_t onoff)
 {
-	mtx_assert(sc->sc_mtx, MA_OWNED);
-
-	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
-		return;
-	}
 	DPRINTF("onoff = %d\n", onoff);
 
 	if (onoff)
-		usb2_com_queue_command(sc, usb2_com_cfg_rts_on, NULL,
-		    &sc->sc_rts_on_task[0].hdr,
-		    &sc->sc_rts_on_task[1].hdr);
+		usb2_com_line_state(sc, UCOM_LS_RTS, 0);
 	else
-		usb2_com_queue_command(sc, usb2_com_cfg_rts_off, NULL,
-		    &sc->sc_rts_off_task[0].hdr,
-		    &sc->sc_rts_off_task[1].hdr);
+		usb2_com_line_state(sc, 0, UCOM_LS_RTS);
 }
 
 static void

==== //depot/projects/usb/src/sys/dev/usb2/serial/usb2_serial.h#14 (text+ko) ====

@@ -148,12 +148,7 @@
 	struct usb2_com_cfg_task	sc_start_task[2];
 	struct usb2_com_cfg_task	sc_open_task[2];
 	struct usb2_com_cfg_task	sc_close_task[2];
-	struct usb2_com_cfg_task	sc_break_on_task[2];
-	struct usb2_com_cfg_task	sc_dtr_on_task[2];
-	struct usb2_com_cfg_task	sc_rts_on_task[2];
-	struct usb2_com_cfg_task	sc_break_off_task[2];
-	struct usb2_com_cfg_task	sc_dtr_off_task[2];
-	struct usb2_com_cfg_task	sc_rts_off_task[2];
+	struct usb2_com_cfg_task	sc_line_state_task[2];
 	struct usb2_com_cfg_task	sc_status_task[2];
 	struct usb2_com_param_task	sc_param_task[2];
 	struct cv sc_cv;
@@ -177,6 +172,13 @@
 	uint8_t	sc_msr;
 	uint8_t	sc_mcr;
 	uint8_t	sc_ttyfreed;		/* set when TTY has been freed */
+	/* programmed line state bits */
+	uint8_t sc_pls_set;		/* set bits */
+	uint8_t sc_pls_clr;		/* cleared bits */
+	uint8_t sc_pls_curr;		/* last state */
+#define	UCOM_LS_DTR	0x01
+#define	UCOM_LS_RTS	0x02
+#define	UCOM_LS_BREAK	0x04
 };
 
 int	usb2_com_attach(struct usb2_com_super_softc *,


More information about the p4-projects mailing list