summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2009-09-05 20:35:31 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2009-09-05 20:35:31 +0000
commit7253faaa748d7bbff8873e80abad87780f221acf (patch)
treea9140bab6083abb5924469785959ff484e7f951c /sys/dev/usb
parenteef0e189694ea93f1e6c2b54a5fce49faa87b2d0 (diff)
Make use of the new wsdisplay ability, committed by miod previously, which
allows our rasops functions to return EAGAIN if our usb command queue is full. This gets us rid of the ugly while { delay(); } loop and makes udl work also on MP kernels now (we faced a deadlock so far because spinning in that delay() loop with biglock active wasn't that much fun). With help from miod@
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/udl.c102
1 files changed, 77 insertions, 25 deletions
diff --git a/sys/dev/usb/udl.c b/sys/dev/usb/udl.c
index 0e8d0bd41b8..3e4f680e78e 100644
--- a/sys/dev/usb/udl.c
+++ b/sys/dev/usb/udl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udl.c,v 1.30 2009/09/05 14:09:35 miod Exp $ */
+/* $OpenBSD: udl.c,v 1.31 2009/09/05 20:35:30 mglocker Exp $ */
/*
* Copyright (c) 2009 Marcus Glocker <mglocker@openbsd.org>
@@ -111,6 +111,8 @@ int udl_cmd_insert_buf_comp(struct udl_softc *, uint8_t *,
uint32_t);
int udl_cmd_insert_head_comp(struct udl_softc *, uint32_t);
void udl_cmd_insert_check(struct udl_cmd_buf *, int);
+uint32_t udl_cmd_get_offset(struct udl_softc *);
+void udl_cmd_set_offset(struct udl_softc *, uint32_t);
void udl_cmd_write_reg_1(struct udl_softc *, uint8_t, uint8_t);
void udl_cmd_write_reg_3(struct udl_softc *, uint8_t, uint32_t);
usbd_status udl_cmd_send(struct udl_softc *);
@@ -555,12 +557,16 @@ udl_copycols(void *cookie, int row, int src, int dst, int num)
struct rasops_info *ri = cookie;
struct udl_softc *sc;
int sx, sy, dx, dy, cx, cy;
+ uint32_t save_offset;
+ usbd_status error;
sc = ri->ri_hw;
DPRINTF(2, "%s: %s: row=%d, src=%d, dst=%d, num=%d\n",
DN(sc), FUNC, row, src, dst, num);
+ save_offset = udl_cmd_get_offset(sc);
+
sx = src * ri->ri_font->fontwidth;
sy = row * ri->ri_font->fontheight;
dx = dst * ri->ri_font->fontwidth;
@@ -570,9 +576,13 @@ udl_copycols(void *cookie, int row, int src, int dst, int num)
(sc->udl_fb_block_copy)(sc, sx, sy, dx, dy, cx, cy);
- (void)udl_cmd_send_async(sc);
+ error = udl_cmd_send_async(sc);
+ if (error != USBD_NORMAL_COMPLETION) {
+ udl_cmd_set_offset(sc, save_offset);
+ return (EAGAIN);
+ }
- return 0;
+ return (0);
}
int
@@ -581,12 +591,16 @@ udl_copyrows(void *cookie, int src, int dst, int num)
struct rasops_info *ri = cookie;
struct udl_softc *sc;
int sy, dy, cx, cy;
+ uint32_t save_offset;
+ usbd_status error;
sc = ri->ri_hw;
DPRINTF(2, "%s: %s: src=%d, dst=%d, num=%d\n",
DN(sc), FUNC, src, dst, num);
+ save_offset = udl_cmd_get_offset(sc);
+
sy = src * sc->sc_ri.ri_font->fontheight;
dy = dst * sc->sc_ri.ri_font->fontheight;
cx = sc->sc_ri.ri_emuwidth;
@@ -598,9 +612,13 @@ udl_copyrows(void *cookie, int src, int dst, int num)
/* copy row block back from off-screen now */
(sc->udl_fb_block_copy)(sc, 0, sc->sc_ri.ri_emuheight, 0, dy, cx, cy);
- (void)udl_cmd_send_async(sc);
+ error = udl_cmd_send_async(sc);
+ if (error != USBD_NORMAL_COMPLETION) {
+ udl_cmd_set_offset(sc, save_offset);
+ return (EAGAIN);
+ }
- return 0;
+ return (0);
}
int
@@ -611,12 +629,16 @@ udl_erasecols(void *cookie, int row, int col, int num, long attr)
uint16_t bgc;
int fg, bg;
int x, y, cx, cy;
+ uint32_t save_offset;
+ usbd_status error;
sc = ri->ri_hw;
DPRINTF(2, "%s: %s: row=%d, col=%d, num=%d\n",
DN(sc), FUNC, row, col, num);
+ save_offset = udl_cmd_get_offset(sc);
+
sc->sc_ri.ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
bgc = (uint16_t)sc->sc_ri.ri_devcmap[bg];
@@ -627,9 +649,13 @@ udl_erasecols(void *cookie, int row, int col, int num, long attr)
udl_fb_block_write(sc, bgc, x, y, cx, cy);
- (void)udl_cmd_send_async(sc);
+ error = udl_cmd_send_async(sc);
+ if (error != USBD_NORMAL_COMPLETION) {
+ udl_cmd_set_offset(sc, save_offset);
+ return (EAGAIN);
+ }
- return 0;
+ return (0);
}
int
@@ -640,11 +666,15 @@ udl_eraserows(void *cookie, int row, int num, long attr)
uint16_t bgc;
int fg, bg;
int x, y, cx, cy;
+ uint32_t save_offset;
+ usbd_status error;
sc = ri->ri_hw;
DPRINTF(2, "%s: %s: row=%d, num=%d\n", DN(sc), FUNC, row, num);
+ save_offset = udl_cmd_get_offset(sc);
+
sc->sc_ri.ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
bgc = (uint16_t)sc->sc_ri.ri_devcmap[bg];
@@ -655,9 +685,13 @@ udl_eraserows(void *cookie, int row, int num, long attr)
udl_fb_block_write(sc, bgc, x, y, cx, cy);
- (void)udl_cmd_send_async(sc);
+ error = udl_cmd_send_async(sc);
+ if (error != USBD_NORMAL_COMPLETION) {
+ udl_cmd_set_offset(sc, save_offset);
+ return (EAGAIN);
+ }
- return 0;
+ return (0);
}
int
@@ -696,7 +730,7 @@ udl_putchar(void *cookie, int row, int col, u_int uc, long attr)
* the buffer.
*/
- return 0;
+ return (0);
}
int
@@ -704,6 +738,9 @@ udl_do_cursor(struct rasops_info *ri)
{
struct udl_softc *sc = ri->ri_hw;
uint32_t x, y;
+ uint32_t save_offset;
+ uint8_t save_cursor;
+ usbd_status error;
/*
* XXX
@@ -716,6 +753,9 @@ udl_do_cursor(struct rasops_info *ri)
DPRINTF(2, "%s: %s: ccol=%d, crow=%d\n",
DN(sc), FUNC, ri->ri_ccol, ri->ri_crow);
+ save_offset = udl_cmd_get_offset(sc);
+ save_cursor = sc->sc_cursor_on;
+
x = ri->ri_ccol * ri->ri_font->fontwidth;
y = ri->ri_crow * ri->ri_font->fontheight;
@@ -737,9 +777,14 @@ udl_do_cursor(struct rasops_info *ri)
sc->sc_cursor_on = 0;
}
- (void)udl_cmd_send_async(sc);
+ error = udl_cmd_send_async(sc);
+ if (error != USBD_NORMAL_COMPLETION) {
+ udl_cmd_set_offset(sc, save_offset);
+ sc->sc_cursor_on = save_cursor;
+ return (EAGAIN);
+ }
- return 0;
+ return (0);
}
/* ---------- */
@@ -1199,6 +1244,22 @@ udl_cmd_insert_check(struct udl_cmd_buf *cb, int len)
}
}
+uint32_t
+udl_cmd_get_offset(struct udl_softc *sc)
+{
+ struct udl_cmd_buf *cb = &sc->sc_cmd_buf;
+
+ return (cb->off);
+}
+
+void
+udl_cmd_set_offset(struct udl_softc *sc, uint32_t offset)
+{
+ struct udl_cmd_buf *cb = &sc->sc_cmd_buf;
+
+ cb->off = offset;
+}
+
void
udl_cmd_write_reg_1(struct udl_softc *sc, uint8_t reg, uint8_t val)
{
@@ -1256,19 +1317,9 @@ udl_cmd_send_async(struct udl_softc *sc)
usbd_status error;
int i, s;
- /* if the ring buffer is full, wait until it's flushed completely */
- if (sc->sc_cmd_xfer_cnt == UDL_CMD_XFER_COUNT) {
- DPRINTF(2, "%s: %s: ring buffer full, wait until flushed\n",
- DN(sc), FUNC);
- /*
- * XXX
- * Yes, this is ugly. But since we can't tsleep() here, I
- * have no better idea how we can delay rasops so it doesn't
- * blow up our command buffer.
- */
- while (sc->sc_cmd_xfer_cnt > 0)
- delay(100);
- }
+ /* check if command queue is full */
+ if (sc->sc_cmd_xfer_cnt == UDL_CMD_XFER_COUNT)
+ return (USBD_IN_USE);
s = splusb(); /* no callbacks please until accounting is done */
@@ -1296,6 +1347,7 @@ udl_cmd_send_async(struct udl_softc *sc)
error = usbd_transfer(cx->xfer);
if (error != 0 && error != USBD_IN_PROGRESS) {
printf("%s: %s: %s!\n", DN(sc), FUNC, usbd_errstr(error));
+ splx(s);
return (error);
}
DPRINTF(2, "%s: %s: sending %d bytes from buffer no. %d\n",