diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2009-09-11 20:12:52 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2009-09-11 20:12:52 +0000 |
commit | ccdcd1684158b6e597659874b6a18201582f02b8 (patch) | |
tree | e3297912d2f7b0a31dfd290010635f59b949ae88 /sys/dev | |
parent | 678af8c675a9d9b235878ee57e1549a330ec4987 (diff) |
Don't panic if the command buffer runs full. Instead try to flush it,
and continue operation afterwards. If we can't flush immediately, we will
undo the operation and return EAGAIN to wsdisplay (like we do already for
the xfer queue).
This allows us to set higher resolutions (tested up to 1280x1024) without
bumping the command buffer or xfer buffer memory further.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/usb/udl.c | 309 | ||||
-rw-r--r-- | sys/dev/usb/udl.h | 22 |
2 files changed, 239 insertions, 92 deletions
diff --git a/sys/dev/usb/udl.c b/sys/dev/usb/udl.c index 68646aef9aa..ec55576092e 100644 --- a/sys/dev/usb/udl.c +++ b/sys/dev/usb/udl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udl.c,v 1.34 2009/09/09 07:01:20 mglocker Exp $ */ +/* $OpenBSD: udl.c,v 1.35 2009/09/11 20:12:51 mglocker Exp $ */ /* * Copyright (c) 2009 Marcus Glocker <mglocker@openbsd.org> @@ -110,7 +110,8 @@ void udl_cmd_insert_buf(struct udl_softc *, uint8_t *, uint32_t); 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); +int udl_cmd_insert_check(struct udl_softc *, int); +void udl_cmd_set_xfer(struct udl_softc *, 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); @@ -124,35 +125,35 @@ usbd_status udl_init_chip(struct udl_softc *); void udl_init_fb_offsets(struct udl_softc *, uint32_t, uint32_t, uint32_t, uint32_t); usbd_status udl_init_resolution(struct udl_softc *, uint8_t *, uint8_t); -void udl_fb_off_write(struct udl_softc *, uint16_t, uint32_t, +int udl_fb_off_write(struct udl_softc *, uint16_t, uint32_t, uint16_t); -void udl_fb_line_write(struct udl_softc *, uint16_t, uint32_t, +int udl_fb_line_write(struct udl_softc *, uint16_t, uint32_t, uint32_t, uint32_t); -void udl_fb_block_write(struct udl_softc *, uint16_t, uint32_t, +int udl_fb_block_write(struct udl_softc *, uint16_t, uint32_t, uint32_t, uint32_t, uint32_t); -void udl_fb_buf_write(struct udl_softc *, uint8_t *, uint32_t, +int udl_fb_buf_write(struct udl_softc *, uint8_t *, uint32_t, uint32_t, uint16_t); -void udl_fb_off_copy(struct udl_softc *, uint32_t, uint32_t, +int udl_fb_off_copy(struct udl_softc *, uint32_t, uint32_t, uint16_t); -void udl_fb_line_copy(struct udl_softc *, uint32_t, uint32_t, +int udl_fb_line_copy(struct udl_softc *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); -void udl_fb_block_copy(struct udl_softc *, uint32_t, uint32_t, +int udl_fb_block_copy(struct udl_softc *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); -void udl_fb_off_write_comp(struct udl_softc *, uint16_t, uint32_t, +int udl_fb_off_write_comp(struct udl_softc *, uint16_t, uint32_t, uint16_t); -void udl_fb_line_write_comp(struct udl_softc *, uint16_t, uint32_t, +int udl_fb_line_write_comp(struct udl_softc *, uint16_t, uint32_t, uint32_t, uint32_t); -void udl_fb_block_write_comp(struct udl_softc *, uint16_t, uint32_t, +int udl_fb_block_write_comp(struct udl_softc *, uint16_t, uint32_t, uint32_t, uint32_t, uint32_t); -void udl_fb_buf_write_comp(struct udl_softc *, uint8_t *, uint32_t, +int udl_fb_buf_write_comp(struct udl_softc *, uint8_t *, uint32_t, uint32_t, uint16_t); -void udl_fb_off_copy_comp(struct udl_softc *, uint32_t, uint32_t, +int udl_fb_off_copy_comp(struct udl_softc *, uint32_t, uint32_t, uint16_t); -void udl_fb_line_copy_comp(struct udl_softc *, uint32_t, uint32_t, +int udl_fb_line_copy_comp(struct udl_softc *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); -void udl_fb_block_copy_comp(struct udl_softc *, uint32_t, uint32_t, +int udl_fb_block_copy_comp(struct udl_softc *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); -void udl_draw_char(struct udl_softc *, uint16_t, uint16_t, u_int, +int udl_draw_char(struct udl_softc *, uint16_t, uint16_t, u_int, uint32_t, uint32_t); #ifdef UDL_DEBUG void udl_hexdump(void *, int, int); @@ -285,6 +286,11 @@ udl_attach(struct device *parent, struct device *self, void *aux) return; /* + * Device initialization is done per synchronous xfers. + */ + udl_cmd_set_xfer(sc, UDL_CMD_XFER_SYNC); + + /* * Initialize chip. */ error = udl_init_chip(sc); @@ -353,6 +359,10 @@ udl_attach_hook(void *arg) #ifdef UDL_DEBUG udl_init_test(sc); #endif + /* + * From this point on we do asynchronous xfers. + */ + udl_cmd_set_xfer(sc, UDL_CMD_XFER_ASYNC); } int @@ -556,7 +566,7 @@ 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; + int sx, sy, dx, dy, cx, cy, r; uint32_t save_offset; usbd_status error; @@ -575,13 +585,20 @@ udl_copycols(void *cookie, int row, int src, int dst, int num) cy = ri->ri_font->fontheight; /* copy row block to off-screen first to fix overlay-copy problem */ - (sc->udl_fb_block_copy)(sc, sx, sy, 0, sc->sc_ri.ri_emuheight, cx, cy); + r = (sc->udl_fb_block_copy) + (sc, sx, sy, 0, sc->sc_ri.ri_emuheight, cx, cy); + if (r != 0) + goto fail; /* copy row block back from off-screen now */ - (sc->udl_fb_block_copy)(sc, 0, sc->sc_ri.ri_emuheight, dx, dy, cx, cy); + r = (sc->udl_fb_block_copy) + (sc, 0, sc->sc_ri.ri_emuheight, dx, dy, cx, cy); + if (r != 0) + goto fail; error = udl_cmd_send_async(sc); if (error != USBD_NORMAL_COMPLETION) { +fail: udl_cmd_set_offset(sc, save_offset); return (EAGAIN); } @@ -594,7 +611,7 @@ udl_copyrows(void *cookie, int src, int dst, int num) { struct rasops_info *ri = cookie; struct udl_softc *sc; - int sy, dy, cx, cy; + int sy, dy, cx, cy, r; uint32_t save_offset; usbd_status error; @@ -611,13 +628,20 @@ udl_copyrows(void *cookie, int src, int dst, int num) cy = num * sc->sc_ri.ri_font->fontheight; /* copy row block to off-screen first to fix overlay-copy problem */ - (sc->udl_fb_block_copy)(sc, 0, sy, 0, sc->sc_ri.ri_emuheight, cx, cy); + r = (sc->udl_fb_block_copy) + (sc, 0, sy, 0, sc->sc_ri.ri_emuheight, cx, cy); + if (r != 0) + goto fail; /* copy row block back from off-screen now */ - (sc->udl_fb_block_copy)(sc, 0, sc->sc_ri.ri_emuheight, 0, dy, cx, cy); + r = (sc->udl_fb_block_copy) + (sc, 0, sc->sc_ri.ri_emuheight, 0, dy, cx, cy); + if (r != 0) + goto fail; error = udl_cmd_send_async(sc); if (error != USBD_NORMAL_COMPLETION) { +fail: udl_cmd_set_offset(sc, save_offset); return (EAGAIN); } @@ -632,7 +656,7 @@ udl_erasecols(void *cookie, int row, int col, int num, long attr) struct udl_softc *sc = ri->ri_hw; uint16_t bgc; int fg, bg; - int x, y, cx, cy; + int x, y, cx, cy, r; uint32_t save_offset; usbd_status error; @@ -651,10 +675,13 @@ udl_erasecols(void *cookie, int row, int col, int num, long attr) cx = num * sc->sc_ri.ri_font->fontwidth; cy = sc->sc_ri.ri_font->fontheight; - udl_fb_block_write(sc, bgc, x, y, cx, cy); + r = udl_fb_block_write(sc, bgc, x, y, cx, cy); + if (r != 0) + goto fail; error = udl_cmd_send_async(sc); if (error != USBD_NORMAL_COMPLETION) { +fail: udl_cmd_set_offset(sc, save_offset); return (EAGAIN); } @@ -669,7 +696,7 @@ udl_eraserows(void *cookie, int row, int num, long attr) struct udl_softc *sc; uint16_t bgc; int fg, bg; - int x, y, cx, cy; + int x, y, cx, cy, r; uint32_t save_offset; usbd_status error; @@ -687,10 +714,13 @@ udl_eraserows(void *cookie, int row, int num, long attr) cx = sc->sc_ri.ri_emuwidth; cy = num * sc->sc_ri.ri_font->fontheight; - udl_fb_block_write(sc, bgc, x, y, cx, cy); + r = udl_fb_block_write(sc, bgc, x, y, cx, cy); + if (r != 0) + goto fail; error = udl_cmd_send_async(sc); if (error != USBD_NORMAL_COMPLETION) { +fail: udl_cmd_set_offset(sc, save_offset); return (EAGAIN); } @@ -703,11 +733,15 @@ udl_putchar(void *cookie, int row, int col, u_int uc, long attr) { struct rasops_info *ri = cookie; struct udl_softc *sc = ri->ri_hw; + int r; uint16_t fgc, bgc; uint32_t x, y, fg, bg; + uint32_t save_offset; DPRINTF(2, "%s: %s\n", DN(sc), FUNC); + save_offset = udl_cmd_get_offset(sc); + sc->sc_ri.ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); fgc = (uint16_t)sc->sc_ri.ri_devcmap[fg]; bgc = (uint16_t)sc->sc_ri.ri_devcmap[bg]; @@ -720,11 +754,15 @@ udl_putchar(void *cookie, int row, int col, u_int uc, long attr) * Writting a block for the space character instead rendering * it from font bits is more slim. */ - (sc->udl_fb_block_write)(sc, bgc, x, y, + r = (sc->udl_fb_block_write)(sc, bgc, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight); + if (r != 0) + goto fail; } else { /* render a character from font bits */ - udl_draw_char(sc, fgc, bgc, uc, x, y); + r = udl_draw_char(sc, fgc, bgc, uc, x, y); + if (r != 0) + goto fail; } /* @@ -735,12 +773,17 @@ udl_putchar(void *cookie, int row, int col, u_int uc, long attr) */ return (0); + +fail: + udl_cmd_set_offset(sc, save_offset); + return (EAGAIN); } int udl_do_cursor(struct rasops_info *ri) { struct udl_softc *sc = ri->ri_hw; + int r; uint32_t x, y; uint32_t save_offset; uint8_t save_cursor; @@ -765,24 +808,31 @@ udl_do_cursor(struct rasops_info *ri) if (sc->sc_cursor_on == 0) { /* save the last character block to off-screen */ - (sc->udl_fb_block_copy)(sc, x, y, 0, sc->sc_ri.ri_emuheight, + r = (sc->udl_fb_block_copy)(sc, x, y, 0, sc->sc_ri.ri_emuheight, ri->ri_font->fontwidth, ri->ri_font->fontheight); + if (r != 0) + goto fail; /* draw cursor */ - (sc->udl_fb_block_write)(sc, 0xffff, x, y, + r = (sc->udl_fb_block_write)(sc, 0xffff, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight); + if (r != 0) + goto fail; sc->sc_cursor_on = 1; } else { /* restore the last saved character from off-screen */ - (sc->udl_fb_block_copy)(sc, 0, sc->sc_ri.ri_emuheight, x, y, + r = (sc->udl_fb_block_copy)(sc, 0, sc->sc_ri.ri_emuheight, x, y, ri->ri_font->fontwidth, ri->ri_font->fontheight); + if (r != 0) + goto fail; sc->sc_cursor_on = 0; } error = udl_cmd_send_async(sc); if (error != USBD_NORMAL_COMPLETION) { +fail: udl_cmd_set_offset(sc, save_offset); sc->sc_cursor_on = save_cursor; return (EAGAIN); @@ -1043,8 +1093,6 @@ udl_cmd_insert_int_1(struct udl_softc *sc, uint8_t value) { struct udl_cmd_buf *cb = &sc->sc_cmd_buf; - udl_cmd_insert_check(cb, 1); - cb->buf[cb->off] = value; cb->off += 1; @@ -1056,8 +1104,6 @@ udl_cmd_insert_int_2(struct udl_softc *sc, uint16_t value) uint16_t lvalue; struct udl_cmd_buf *cb = &sc->sc_cmd_buf; - udl_cmd_insert_check(cb, 2); - lvalue = htobe16(value); bcopy(&lvalue, cb->buf + cb->off, 2); @@ -1069,8 +1115,6 @@ udl_cmd_insert_int_3(struct udl_softc *sc, uint32_t value) { uint32_t lvalue; struct udl_cmd_buf *cb = &sc->sc_cmd_buf; - - udl_cmd_insert_check(cb, 3); #if BYTE_ORDER == BIG_ENDIAN lvalue = htobe32(value) << 8; #else @@ -1087,8 +1131,6 @@ udl_cmd_insert_int_4(struct udl_softc *sc, uint32_t value) uint32_t lvalue; struct udl_cmd_buf *cb = &sc->sc_cmd_buf; - udl_cmd_insert_check(cb, 4); - lvalue = htobe32(value); bcopy(&lvalue, cb->buf + cb->off, 4); @@ -1100,8 +1142,6 @@ udl_cmd_insert_buf(struct udl_softc *sc, uint8_t *buf, uint32_t len) { struct udl_cmd_buf *cb = &sc->sc_cmd_buf; - udl_cmd_insert_check(cb, len); - bcopy(buf, cb->buf + cb->off, len); cb->off += len; @@ -1118,8 +1158,6 @@ udl_cmd_insert_buf_comp(struct udl_softc *sc, uint8_t *buf, uint32_t len) uint32_t bit_count, bit_pattern, bit_cur; int i, j, bytes, eob, padding, next; - udl_cmd_insert_check(cb, len); - pixels = (uint16_t *)buf; bit_pos = bytes = eob = padding = 0; @@ -1215,8 +1253,6 @@ udl_cmd_insert_head_comp(struct udl_softc *sc, uint32_t len) struct udl_cmd_buf *cb = &sc->sc_cmd_buf; int i, padding; - udl_cmd_insert_check(cb, len); - if (cb->compblock > UDL_CB_BODY_SIZE) { cb->off -= UDL_CMD_COPY_HEAD_SIZE; cb->compblock -= UDL_CMD_COPY_HEAD_SIZE; @@ -1235,17 +1271,37 @@ udl_cmd_insert_head_comp(struct udl_softc *sc, uint32_t len) return (len); } -void -udl_cmd_insert_check(struct udl_cmd_buf *cb, int len) +int +udl_cmd_insert_check(struct udl_softc *sc, int len) { + struct udl_cmd_buf *cb = &sc->sc_cmd_buf; int total; + usbd_status error; total = cb->off + len; - if (total >= UDL_CMD_MAX_XFER_SIZE) { - /* XXX */ - panic("udl_cmd_insert_check: command buffer is full"); + if (total > UDL_CMD_MAX_XFER_SIZE) { + /* command buffer is almost full, try to flush it */ + if (cb->xfer_method == UDL_CMD_XFER_ASYNC) + error = udl_cmd_send_async(sc); + else + error = udl_cmd_send(sc); + if (error != USBD_NORMAL_COMPLETION) { + DPRINTF(1, "%s: %s: can't flush full command buffer\n", + DN(sc), FUNC); + return (EAGAIN); + } } + + return (0); +} + +void +udl_cmd_set_xfer(struct udl_softc *sc, int xfer_method) +{ + struct udl_cmd_buf *cb = &sc->sc_cmd_buf; + + cb->xfer_method = xfer_method; } uint32_t @@ -1490,14 +1546,18 @@ udl_init_resolution(struct udl_softc *sc, uint8_t *buf, uint8_t len) return (USBD_NORMAL_COMPLETION); } -void +int udl_fb_off_write(struct udl_softc *sc, uint16_t rgb16, uint32_t off, uint16_t width) { uint8_t buf[UDL_CMD_MAX_DATA_SIZE]; uint16_t lwidth, lrgb16; uint32_t loff; - int i; + int i, r; + + r = udl_cmd_insert_check(sc, UDL_CMD_WRITE_MAX_SIZE); + if (r != 0) + return (r); loff = off * 2; lwidth = width * 2; @@ -1513,13 +1573,16 @@ udl_fb_off_write(struct udl_softc *sc, uint16_t rgb16, uint32_t off, } udl_cmd_insert_buf(sc, buf, lwidth); + + return (0); } -void +int udl_fb_line_write(struct udl_softc *sc, uint16_t rgb16, uint32_t x, uint32_t y, uint32_t width) { uint32_t off, block; + int r; off = (y * sc->sc_width) + x; @@ -1529,29 +1592,44 @@ udl_fb_line_write(struct udl_softc *sc, uint16_t rgb16, uint32_t x, else block = width; - udl_fb_off_write(sc, rgb16, off, block); + r = udl_fb_off_write(sc, rgb16, off, block); + if (r != 0) + return (r); off += block; width -= block; } + + return (0); } -void +int udl_fb_block_write(struct udl_softc *sc, uint16_t rgb16, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { uint32_t i; + int r; + + for (i = 0; i < height; i++) { + r = udl_fb_line_write(sc, rgb16, x, y + i, width); + if (r != 0) + return (r); + } - for (i = 0; i < height; i++) - udl_fb_line_write(sc, rgb16, x, y + i, width); + return (0); } -void +int udl_fb_buf_write(struct udl_softc *sc, uint8_t *buf, uint32_t x, uint32_t y, uint16_t width) { uint16_t lwidth; uint32_t off; + int r; + + r = udl_cmd_insert_check(sc, UDL_CMD_WRITE_MAX_SIZE); + if (r != 0) + return (r); off = ((y * sc->sc_width) + x) * 2; lwidth = width * 2; @@ -1562,13 +1640,20 @@ udl_fb_buf_write(struct udl_softc *sc, uint8_t *buf, uint32_t x, udl_cmd_insert_int_1(sc, width >= UDL_CMD_MAX_PIXEL_COUNT ? 0 : width); udl_cmd_insert_buf(sc, buf, lwidth); + + return (0); } -void +int udl_fb_off_copy(struct udl_softc *sc, uint32_t src_off, uint32_t dst_off, uint16_t width) { uint32_t ldst_off, lsrc_off; + int r; + + r = udl_cmd_insert_check(sc, UDL_CMD_COPY_MAX_SIZE); + if (r != 0) + return (r); ldst_off = dst_off * 2; lsrc_off = src_off * 2; @@ -1578,13 +1663,16 @@ udl_fb_off_copy(struct udl_softc *sc, uint32_t src_off, uint32_t dst_off, udl_cmd_insert_int_3(sc, ldst_off); udl_cmd_insert_int_1(sc, width >= UDL_CMD_MAX_PIXEL_COUNT ? 0 : width); udl_cmd_insert_int_3(sc, lsrc_off); + + return (0); } -void +int udl_fb_line_copy(struct udl_softc *sc, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, uint32_t width) { uint32_t src_off, dst_off, block; + int r; src_off = (src_y * sc->sc_width) + src_x; dst_off = (dst_y * sc->sc_width) + dst_x; @@ -1595,25 +1683,35 @@ udl_fb_line_copy(struct udl_softc *sc, uint32_t src_x, uint32_t src_y, else block = width; - udl_fb_off_copy(sc, src_off, dst_off, block); + r = udl_fb_off_copy(sc, src_off, dst_off, block); + if (r != 0) + return (r); src_off += block; dst_off += block; width -= block; } + + return (0); } -void +int udl_fb_block_copy(struct udl_softc *sc, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, uint32_t width, uint32_t height) { - int i; + int i, r; + + for (i = 0; i < height; i++) { + r = udl_fb_line_copy(sc, src_x, src_y + i, dst_x, dst_y + i, + width); + if (r != 0) + return (r); + } - for (i = 0; i < height; i++) - udl_fb_line_copy(sc, src_x, src_y + i, dst_x, dst_y + i, width); + return (0); } -void +int udl_fb_off_write_comp(struct udl_softc *sc, uint16_t rgb16, uint32_t off, uint16_t width) { @@ -1624,6 +1722,10 @@ udl_fb_off_write_comp(struct udl_softc *sc, uint16_t rgb16, uint32_t off, uint32_t loff; int i, r, sent; + r = udl_cmd_insert_check(sc, UDL_CMD_WRITE_MAX_SIZE); + if (r != 0) + return (r); + loff = off * 2; lwidth = width * 2; @@ -1659,13 +1761,16 @@ udl_fb_off_write_comp(struct udl_softc *sc, uint16_t rgb16, uint32_t off, } sent += r; } + + return (0); } -void +int udl_fb_line_write_comp(struct udl_softc *sc, uint16_t rgb16, uint32_t x, uint32_t y, uint32_t width) { uint32_t off, block; + int r; off = (y * sc->sc_width) + x; @@ -1675,24 +1780,34 @@ udl_fb_line_write_comp(struct udl_softc *sc, uint16_t rgb16, uint32_t x, else block = width; - (sc->udl_fb_off_write)(sc, rgb16, off, block); + r = (sc->udl_fb_off_write)(sc, rgb16, off, block); + if (r != 0) + return (r); off += block; width -= block; } + + return (0); } -void +int udl_fb_block_write_comp(struct udl_softc *sc, uint16_t rgb16, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { uint32_t i; + int r; + + for (i = 0; i < height; i++) { + r = udl_fb_line_write_comp(sc, rgb16, x, y + i, width); + if (r != 0) + return (r); + } - for (i = 0; i < height; i++) - udl_fb_line_write_comp(sc, rgb16, x, y + i, width); + return (0); } -void +int udl_fb_buf_write_comp(struct udl_softc *sc, uint8_t *buf, uint32_t x, uint32_t y, uint16_t width) { @@ -1702,6 +1817,10 @@ udl_fb_buf_write_comp(struct udl_softc *sc, uint8_t *buf, uint32_t x, uint32_t off; int r, sent; + r = udl_cmd_insert_check(sc, UDL_CMD_WRITE_MAX_SIZE); + if (r != 0) + return (r); + off = ((y * sc->sc_width) + x) * 2; lwidth = width * 2; @@ -1732,9 +1851,11 @@ udl_fb_buf_write_comp(struct udl_softc *sc, uint8_t *buf, uint32_t x, } sent += r; } + + return (0); } -void +int udl_fb_off_copy_comp(struct udl_softc *sc, uint32_t src_off, uint32_t dst_off, uint16_t width) { @@ -1742,6 +1863,10 @@ udl_fb_off_copy_comp(struct udl_softc *sc, uint32_t src_off, uint32_t dst_off, uint32_t ldst_off, lsrc_off; int r; + r = udl_cmd_insert_check(sc, UDL_CMD_COPY_MAX_SIZE); + if (r != 0) + return (r); + ldst_off = dst_off * 2; lsrc_off = src_off * 2; @@ -1765,13 +1890,16 @@ udl_fb_off_copy_comp(struct udl_softc *sc, uint32_t src_off, uint32_t dst_off, r = udl_cmd_insert_head_comp(sc, UDL_CMD_COPY_HEAD_SIZE); } + + return (0); } -void +int udl_fb_line_copy_comp(struct udl_softc *sc, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, uint32_t width) { uint32_t src_off, dst_off, block; + int r; src_off = (src_y * sc->sc_width) + src_x; dst_off = (dst_y * sc->sc_width) + dst_x; @@ -1782,30 +1910,39 @@ udl_fb_line_copy_comp(struct udl_softc *sc, uint32_t src_x, uint32_t src_y, else block = width; - udl_fb_off_copy_comp(sc, src_off, dst_off, block); + r = udl_fb_off_copy_comp(sc, src_off, dst_off, block); + if (r != 0) + return (r); src_off += block; dst_off += block; width -= block; } + + return (0); } -void +int udl_fb_block_copy_comp(struct udl_softc *sc, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, uint32_t width, uint32_t height) { - int i; + int i, r; - for (i = 0; i < height; i++) - udl_fb_line_copy_comp(sc, src_x, src_y + i, dst_x, dst_y + i, - width); + for (i = 0; i < height; i++) { + r = udl_fb_line_copy_comp(sc, src_x, src_y + i, + dst_x, dst_y + i, width); + if (r != 0) + return (r); + } + + return (0); } -void +int udl_draw_char(struct udl_softc *sc, uint16_t fg, uint16_t bg, u_int uc, uint32_t x, uint32_t y) { - int i, j, ly; + int i, j, ly, r; uint8_t *fontchar; uint8_t buf[UDL_CMD_MAX_DATA_SIZE]; uint16_t *line, lrgb16, fontbits, luc; @@ -1833,11 +1970,15 @@ udl_draw_char(struct udl_softc *sc, uint16_t fg, uint16_t bg, u_int uc, bcopy(&lrgb16, line, 2); line++; } - (sc->udl_fb_buf_write)(sc, buf, x, ly, font->fontwidth); + r = (sc->udl_fb_buf_write)(sc, buf, x, ly, font->fontwidth); + if (r != 0) + return (r); ly++; fontchar += font->stride; } + + return (0); } /* ---------- */ diff --git a/sys/dev/usb/udl.h b/sys/dev/usb/udl.h index c278dc2e5c1..b342b3f9148 100644 --- a/sys/dev/usb/udl.h +++ b/sys/dev/usb/udl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: udl.h,v 1.6 2009/08/27 19:43:50 mglocker Exp $ */ +/* $OpenBSD: udl.h,v 1.7 2009/09/11 20:12:51 mglocker Exp $ */ /* * Copyright (c) 2009 Marcus Glocker <mglocker@openbsd.org> @@ -24,6 +24,9 @@ #define UDL_CMD_MAX_PIXEL_COUNT (UDL_CMD_MAX_DATA_SIZE / 2) #define UDL_CMD_WRITE_HEAD_SIZE 6 #define UDL_CMD_COPY_HEAD_SIZE 9 +#define UDL_CMD_WRITE_MAX_SIZE (UDL_CMD_WRITE_HEAD_SIZE + \ + UDL_CMD_MAX_DATA_SIZE + 2) +#define UDL_CMD_COPY_MAX_SIZE (UDL_CMD_COPY_HEAD_SIZE + 2) struct udl_cmd_xfer { struct udl_softc *sc; @@ -33,6 +36,9 @@ struct udl_cmd_xfer { }; struct udl_cmd_buf { +#define UDL_CMD_XFER_SYNC 0 +#define UDL_CMD_XFER_ASYNC 1 + uint8_t xfer_method; uint16_t compblock; uint32_t off; uint8_t *buf; @@ -68,25 +74,25 @@ struct udl_softc { * functions so we can easily differ between compressed and * none-compressed mode. */ - void (*udl_fb_off_write) + int (*udl_fb_off_write) (struct udl_softc *, uint16_t, uint32_t, uint16_t); - void (*udl_fb_line_write) + int (*udl_fb_line_write) (struct udl_softc *, uint16_t, uint32_t, uint32_t, uint32_t); - void (*udl_fb_block_write) + int (*udl_fb_block_write) (struct udl_softc *, uint16_t, uint32_t, uint32_t, uint32_t, uint32_t); - void (*udl_fb_buf_write) + int (*udl_fb_buf_write) (struct udl_softc *, uint8_t *, uint32_t, uint32_t, uint16_t); - void (*udl_fb_off_copy) + int (*udl_fb_off_copy) (struct udl_softc *, uint32_t, uint32_t, uint16_t); - void (*udl_fb_line_copy) + int (*udl_fb_line_copy) (struct udl_softc *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); - void (*udl_fb_block_copy) + int (*udl_fb_block_copy) (struct udl_softc *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); }; |