diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-04-20 20:26:27 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-04-20 20:26:27 +0000 |
commit | accdbc74a18b329dfe8165719c71f6fa9e41c895 (patch) | |
tree | d60ff467645625c7b5f3e7501142f7df8d9928f4 /sys/arch | |
parent | 077c5931125faad0fd35f66d4770047ea969c014 (diff) |
Do not wait too long for the chip to unbusy, and return EAGAIN to the upper
layers when the chip can't process commands fast enough; wscons knows how to
cope.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sgi/gio/newport.c | 114 | ||||
-rw-r--r-- | sys/arch/sgi/gio/newportreg.h | 6 |
2 files changed, 77 insertions, 43 deletions
diff --git a/sys/arch/sgi/gio/newport.c b/sys/arch/sgi/gio/newport.c index eeb7e176779..d31fa91e452 100644 --- a/sys/arch/sgi/gio/newport.c +++ b/sys/arch/sgi/gio/newport.c @@ -1,4 +1,4 @@ -/* $OpenBSD: newport.c,v 1.5 2012/10/03 22:46:09 miod Exp $ */ +/* $OpenBSD: newport.c,v 1.6 2013/04/20 20:26:26 miod Exp $ */ /* $NetBSD: newport.c,v 1.15 2009/05/12 23:51:25 macallan Exp $ */ /* @@ -144,8 +144,7 @@ static __inline__ void rex3_write_go(struct newport_devconfig *, bus_size_t, uint32_t); static __inline__ uint32_t rex3_read(struct newport_devconfig *, bus_size_t); -static __inline__ -void rex3_wait_gfifo(struct newport_devconfig *); +int rex3_wait_gfifo(struct newport_devconfig *, const char *); void vc2_write_ireg(struct newport_devconfig *, uint8_t, uint16_t); uint16_t vc2_read_ireg(struct newport_devconfig *, uint8_t); @@ -157,14 +156,14 @@ void xmap9_write_mode(struct newport_devconfig *, uint8_t, uint32_t); void newport_attach_common(struct newport_devconfig *, struct gio_attach_args *); -void newport_bitblt(struct newport_devconfig *, int, int, int, int, int, int, +int newport_bitblt(struct newport_devconfig *, int, int, int, int, int, int, int); void newport_cmap_setrgb(struct newport_devconfig *, int, uint8_t, uint8_t, uint8_t); -void newport_fill_rectangle(struct newport_devconfig *, int, int, int, int, +int newport_fill_rectangle(struct newport_devconfig *, int, int, int, int, int); void newport_get_resolution(struct newport_devconfig *); -void newport_init_screen(struct newport_devconfig *); +int newport_init_screen(struct newport_devconfig *); void newport_setup_hw(struct newport_devconfig *); static struct newport_devconfig newport_console_dc; @@ -190,11 +189,23 @@ rex3_read(struct newport_devconfig *dc, bus_size_t rexreg) rexreg); } -static __inline__ void -rex3_wait_gfifo(struct newport_devconfig *dc) +int +rex3_wait_gfifo(struct newport_devconfig *dc, const char *from) { - while (rex3_read(dc, REX3_REG_STATUS) & REX3_STATUS_GFXBUSY) - ; + unsigned int iter; + uint32_t rxstatus; + + for (iter = 100000; iter != 0; iter--) { + rxstatus = rex3_read(dc, REX3_REG_STATUS); + if ((rxstatus & + (REX3_STATUS_GFXBUSY | REX3_STATUS_FIFOLEVEL_MASK)) == 0) + return 0; + } + +#ifdef DEBUG + printf("%s: failed to idle, %05x\n", from, rxstatus); +#endif + return EAGAIN; } void @@ -296,13 +307,14 @@ xmap9_write_mode(struct newport_devconfig *dc, uint8_t index, uint32_t mode) } /**** Helper functions ****/ -void +int newport_fill_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2, int y2, int bg) { struct rasops_info *ri = &dc->dc_ri; - rex3_wait_gfifo(dc); + if (rex3_wait_gfifo(dc, __func__) != 0) + return EAGAIN; rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW | REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP | @@ -317,16 +329,20 @@ newport_fill_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2, rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1); rex3_write_go(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2); + + return 0; } -void +int newport_bitblt(struct newport_devconfig *dc, int xs, int ys, int xd, int yd, int wi, int he, int rop) { int xe, ye; uint32_t tmp; - rex3_wait_gfifo(dc); + if (rex3_wait_gfifo(dc, __func__) != 0) + return EAGAIN; + if (yd > ys) { /* need to copy bottom up */ ye = ys; @@ -358,6 +374,8 @@ newport_bitblt(struct newport_devconfig *dc, int xs, int ys, int xd, tmp |= (xd - xs) << REX3_XYMOVE_XSHIFT; rex3_write_go(dc, REX3_REG_XYMOVE, tmp); + + return 0; } void @@ -505,6 +523,7 @@ newport_attach(struct device *parent, struct device *self, void *aux) struct wsemuldisplaydev_attach_args waa; const char *descr; extern struct consdev wsdisplay_cons; + int fail = 0; if (cn_tab == &wsdisplay_cons && ga->ga_addr == newport_console_dc.dc_addr) { @@ -516,7 +535,8 @@ newport_attach(struct device *parent, struct device *self, void *aux) dc = malloc(sizeof(struct newport_devconfig), M_DEVBUF, M_WAITOK | M_ZERO); newport_attach_common(dc, ga); - newport_init_screen(dc); + if (newport_init_screen(dc) != 0) + fail = 1; } sc->sc_dc = dc; dc->dc_sc = sc; @@ -528,6 +548,16 @@ newport_attach(struct device *parent, struct device *self, void *aux) descr, dc->dc_boardrev, dc->dc_xmaprev, dc->dc_vc2rev); printf("%s: %dx%d %d-bit frame buffer\n", self->dv_xname, dc->dc_xres, dc->dc_yres, dc->dc_depth); +#ifdef DEBUG + printf("%s: REX3 config = %06x\n", + self->dv_xname, rex3_read(dc, REX3_REG_CONFIG)); +#endif + + if (fail) { + printf("%s: failed to initialize screen\n", self->dv_xname); + free(dc, M_DEVBUF); + return; + } sc->sc_scrlist[0] = &dc->dc_wsd; sc->sc_wsl.nscreens = 1; @@ -552,9 +582,12 @@ newport_cnattach(struct gio_attach_args *ga) { struct rasops_info *ri = &newport_console_dc.dc_ri; long defattr; + int rc; newport_attach_common(&newport_console_dc, ga); - newport_init_screen(&newport_console_dc); + rc = newport_init_screen(&newport_console_dc); + if (rc != 0) + return rc; ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr); wsdisplay_cnattach(&newport_console_dc.dc_wsd, ri, 0, 0, defattr); @@ -573,10 +606,11 @@ newport_attach_common(struct newport_devconfig *dc, struct gio_attach_args *ga) newport_get_resolution(dc); } -void +int newport_init_screen(struct newport_devconfig *dc) { struct rasops_info *ri = &dc->dc_ri; + int rc; memset(ri, 0, sizeof(struct rasops_info)); ri->ri_hw = dc; @@ -604,12 +638,14 @@ newport_init_screen(struct newport_devconfig *dc) dc->dc_wsd.fontheight = ri->ri_font->fontheight; dc->dc_wsd.capabilities = ri->ri_caps; - newport_fill_rectangle(dc, 0, 0, ri->ri_width - 1, ri->ri_height - 1, - WSCOL_BLACK); + rc = newport_fill_rectangle(dc, 0, 0, ri->ri_width - 1, + ri->ri_height - 1, WSCOL_BLACK); #ifdef notyet dc->dc_mode = WSDISPLAYIO_MODE_EMUL; #endif + + return rc; } /**** wsdisplay textops ****/ @@ -625,9 +661,8 @@ newport_do_cursor(struct rasops_info *ri) x = ri->ri_ccol * w + ri->ri_xorigin; y = ri->ri_crow * h + ri->ri_yorigin; - newport_bitblt(dc, x, y, x, y, w, h, OPENGL_LOGIC_OP_COPY_INVERTED); - - return 0; + return newport_bitblt(dc, x, y, x, y, w, h, + OPENGL_LOGIC_OP_COPY_INVERTED); } int @@ -646,12 +681,12 @@ newport_putchar(void *c, int row, int col, u_int ch, long attr) ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul); if ((ch == ' ' || ch == 0) && ul == 0) { - newport_fill_rectangle(dc, x, y, x + font->fontwidth - 1, + return newport_fill_rectangle(dc, x, y, x + font->fontwidth - 1, y + font->fontheight - 1, bg); - return 0; } - rex3_wait_gfifo(dc); + if (rex3_wait_gfifo(dc, __func__) != 0) + return EAGAIN; rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW | REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_STOPONX | @@ -710,9 +745,8 @@ newport_copycols(void *c, int row, int srccol, int dstcol, int ncols) y = ri->ri_yorigin + font->fontheight * row; width = font->fontwidth * ncols; height = font->fontheight; - newport_bitblt(dc, xs, y, xd, y, width, height, OPENGL_LOGIC_OP_COPY); - - return 0; + return newport_bitblt(dc, xs, y, xd, y, width, height, + OPENGL_LOGIC_OP_COPY); } int @@ -731,9 +765,7 @@ newport_erasecols(void *c, int row, int startcol, int ncols, long attr) dx = sx + ncols * font->fontwidth - 1; dy = sy + font->fontheight - 1; - newport_fill_rectangle(dc, sx, sy, dx, dy, bg); - - return 0; + return newport_fill_rectangle(dc, sx, sy, dx, dy, bg); } int @@ -750,9 +782,8 @@ newport_copyrows(void *c, int srcrow, int dstrow, int nrows) width = ri->ri_emuwidth; height = font->fontheight * nrows; - newport_bitblt(dc, x, ys, x, yd, width, height, OPENGL_LOGIC_OP_COPY); - - return 0; + return newport_bitblt(dc, x, ys, x, yd, width, height, + OPENGL_LOGIC_OP_COPY); } int @@ -766,17 +797,14 @@ newport_eraserows(void *c, int startrow, int nrows, long attr) ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, NULL); if (nrows == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) { - newport_fill_rectangle(dc, 0, 0, ri->ri_width - 1, + return newport_fill_rectangle(dc, 0, 0, ri->ri_width - 1, ri->ri_height - 1, bg); - return 0; } - newport_fill_rectangle(dc, ri->ri_xorigin, + return newport_fill_rectangle(dc, ri->ri_xorigin, ri->ri_yorigin + startrow * font->fontheight, ri->ri_xorigin + ri->ri_emuwidth - 1, ri->ri_yorigin + (startrow + nrows) * font->fontheight - 1, bg); - - return 0; } /**** wsdisplay accessops ****/ @@ -842,11 +870,13 @@ newport_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) case WSDISPLAYIO_SMODE: nmode = *(int *)data; if (nmode != dc->dc_mode) { - dc->dc_mode = nmode; if (nmode == WSDISPLAYIO_MODE_EMUL) { - rex3_wait_gfifo(dc); + if (rex3_wait_gfifo(dc, __func__) != 0) + return EAGAIN; + dc->dc_mode = nmode; newport_setup_hw(dc); - } + } else + dc->dc_mode = nmode; } break; #endif diff --git a/sys/arch/sgi/gio/newportreg.h b/sys/arch/sgi/gio/newportreg.h index 92bb3ba4f50..457d36d1cdb 100644 --- a/sys/arch/sgi/gio/newportreg.h +++ b/sys/arch/sgi/gio/newportreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: newportreg.h,v 1.1 2012/04/16 22:31:36 miod Exp $ */ +/* $OpenBSD: newportreg.h,v 1.2 2013/04/20 20:26:26 miod Exp $ */ /* $NetBSD: newportreg.h,v 1.5 2011/02/20 07:59:50 matt Exp $ */ /* @@ -174,8 +174,12 @@ #define REX3_REG_TOPSCAN 0x1320 #define REX3_REG_XYWIN 0x1324 +#define REX3_REG_CONFIG 0x1330 + #define REX3_REG_STATUS 0x1338 #define REX3_STATUS_GFXBUSY 0x00000008 +#define REX3_STATUS_FIFOLEVEL_MASK 0x00001F80 +#define REX3_STATUS_FIFOLEVEL_SHIFT 7 /* VC2 */ |