diff --git a/sys/dev/fb/creator.c b/sys/dev/fb/creator.c index 00cf4149b7fa..13c894e219f7 100644 --- a/sys/dev/fb/creator.c +++ b/sys/dev/fb/creator.c @@ -22,22 +22,22 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include #include #include -#include #include +#include #include #include #include #include - -#include +#include #include #include @@ -85,6 +85,8 @@ static void creator_ras_fifo_wait(struct creator_softc *sc, int n); static void creator_ras_setbg(struct creator_softc *sc, int bg); static void creator_ras_setfg(struct creator_softc *sc, int fg); static void creator_ras_wait(struct creator_softc *sc); +static void creator_cursor_enable(struct creator_softc *, int); +static void creator_cursor_install(struct creator_softc *); static video_switch_t creatorvidsw = { .probe = creator_probe, @@ -151,57 +153,6 @@ static int cmap[] = { C(0xff, 0xff, 0xff), /* white */ }; -#define TODO printf("%s: unimplemented\n", __func__) - -static struct creator_softc creator_softc; - -static int -creator_configure(int flags) -{ - struct upa_regs reg[FFB_NREG]; - struct creator_softc *sc; - phandle_t chosen; - ihandle_t stdout; - phandle_t child; - char buf[32]; - int i; - - sc = &creator_softc; - for (child = OF_child(OF_peer(0)); child != 0; - child = OF_peer(child)) { - OF_getprop(child, "name", buf, sizeof(buf)); - if (strcmp(buf, "SUNW,ffb") == 0 || - strcmp(buf, "SUNW,afb") == 0) - break; - } - if (child == 0) - return (0); - - chosen = OF_finddevice("/chosen"); - OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); - if (child == OF_instance_to_package(stdout)) - sc->sc_console = 1; - - OF_getprop(child, "reg", reg, sizeof(reg)); - for (i = 0; i < FFB_NREG; i++) { - sc->sc_bt[i] = &nexus_bustag; - sc->sc_bh[i] = UPA_REG_PHYS(reg + i); - } - OF_getprop(child, "height", &sc->sc_height, sizeof(sc->sc_height)); - OF_getprop(child, "width", &sc->sc_width, sizeof(sc->sc_width)); - - creator_init(0, &sc->sc_va, 0); - - return (0); -} - -static int -creator_probe(int unit, video_adapter_t **adp, void *arg, int flags) -{ - TODO; - return (0); -} - static u_char creator_mouse_pointer[64][8] __aligned(8) = { { 0x00, 0x00, }, /* ............ */ { 0x80, 0x00, }, /* *........... */ @@ -227,6 +178,65 @@ static u_char creator_mouse_pointer[64][8] __aligned(8) = { { 0x00, 0x00, }, /* ............ */ }; +static struct creator_softc creator_softc; + +static int +creator_configure(int flags) +{ + struct upa_regs reg[FFB_NREG]; + struct creator_softc *sc; + phandle_t chosen; + phandle_t output; + ihandle_t stdout; + char buf[32]; + int i; + + sc = &creator_softc; + if ((chosen = OF_finddevice("/chosen")) == -1) + return (0); + if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) + return (0); + if ((output = OF_instance_to_package(stdout)) == -1) + return (0); + if (OF_getprop(output, "name", buf, sizeof(buf)) == -1) + return (0); + if (strcmp(buf, "SUNW,ffb") == 0 || strcmp(buf, "SUNW,afb") == 0) { + /* + * When being called a second time, i.e. during + * sc_probe_unit(), just return at this point. + * Note that the polarity of the VIO_PROBE_ONLY + * flag is somewhat non-intuitive. + */ + if (!(flags & VIO_PROBE_ONLY)) + goto found; + if (strcmp(buf, "SUNW,afb") == 0) + sc->sc_flags |= CREATOR_AFB; + sc->sc_node = output; + } else + return (0); + + if (OF_getprop(output, "reg", reg, sizeof(reg)) == -1) + return (0); + for (i = 0; i < FFB_NREG; i++) { + sc->sc_bt[i] = &nexus_bustag; + sc->sc_bh[i] = UPA_REG_PHYS(reg + i); + } + + if (creator_init(0, &sc->sc_va, 0) < 0) + return (0); + + found: + /* Return number of found adapters. */ + return (1); +} + +static int +creator_probe(int unit, video_adapter_t **adpp, void *arg, int flags) +{ + + return (0); +} + static int creator_init(int unit, video_adapter_t *adp, int flags) { @@ -234,22 +244,30 @@ creator_init(int unit, video_adapter_t *adp, int flags) phandle_t options; video_info_t *vi; char buf[32]; - cell_t col; - cell_t row; - int i, j; sc = (struct creator_softc *)adp; vi = &adp->va_info; - vid_init_struct(adp, "creator", -1, unit); + vid_init_struct(adp, CREATOR_DRIVER_NAME, -1, unit); - options = OF_finddevice("/options"); - OF_getprop(options, "screen-#rows", buf, sizeof(buf)); + if (OF_getprop(sc->sc_node, "height", &sc->sc_height, + sizeof(sc->sc_height)) == -1) + return (ENXIO); + if (OF_getprop(sc->sc_node, "width", &sc->sc_width, + sizeof(sc->sc_width)) == -1) + return (ENXIO); + if ((options = OF_finddevice("/options")) == -1) + return (ENXIO); + if (OF_getprop(options, "screen-#rows", buf, sizeof(buf)) == -1) + return (ENXIO); vi->vi_height = strtol(buf, NULL, 10); - OF_getprop(options, "screen-#columns", buf, sizeof(buf)); + if (OF_getprop(options, "screen-#columns", buf, sizeof(buf)) == -1) + return (ENXIO); vi->vi_width = strtol(buf, NULL, 10); vi->vi_cwidth = 12; vi->vi_cheight = 22; + vi->vi_flags = V_INFO_COLOR; + vi->vi_mem_model = V_INFO_MM_OTHER; sc->sc_font = gallant12x22_data; sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; @@ -267,42 +285,30 @@ creator_init(int unit, video_adapter_t *adp, int flags) FFB_WRITE(sc, FFB_FBC, FFB_FBC_FBC, FFB_FBC_WB_A | FFB_FBC_RB_A | FFB_FBC_SB_BOTH | FFB_FBC_XE_OFF | FFB_FBC_RGBE_MASK); - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, 0x8000); - sc->sc_dac = (FFB_READ(sc, FFB_DAC, FFB_DAC_VALUE) >> 0x1c); - - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, 0x102); - FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0xffffff); - FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0x0); - - for (i = 0; i < 2; i++) { - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, i ? 0x0 : 0x80); - for (j = 0; j < 64; j++) { - FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, - *(uint32_t *)(&creator_mouse_pointer[j][0])); - FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, - *(uint32_t *)(&creator_mouse_pointer[j][4])); + if (!(sc->sc_flags & CREATOR_AFB)) { + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, FFB_DAC_CFG_DID); + if (((FFB_READ(sc, FFB_DAC, FFB_DAC_VALUE) & + FFB_DAC_CFG_DID_PNUM) >> 12) != 0x236e) { + sc->sc_flags |= CREATOR_PAC1; + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, FFB_DAC_CFG_UCTRL); + if (((FFB_READ(sc, FFB_DAC, FFB_DAC_VALUE) & + FFB_DAC_UCTRL_MANREV) >> 8) <= 2) + sc->sc_flags |= CREATOR_CURINV; } } - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, 0x100); - FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0x0); + /* + * FFB_DAC_CFG_TGEN_VIDE must be turned on for creator_set_mode() + * to take effect. + */ + creator_blank_display(adp, V_DISPLAY_ON); + creator_set_mode(adp, 0); + creator_blank_display(adp, V_DISPLAY_BLANK); - if (sc->sc_console) { - col = 0; - row = 0; - OF_interpret("stdout @ is my-self addr line# addr column# ", - 2, &col, &row); - if (col != 0 && row != 0) { - sc->sc_colp = (int *)(col + 4); - sc->sc_rowp = (int *)(row + 4); - } - } else { - creator_blank_display(&sc->sc_va, V_DISPLAY_ON); - } - - creator_set_mode(&sc->sc_va, 0); - - vid_register(&sc->sc_va); + adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER | V_ADP_INITIALIZED; + if (vid_register(adp) < 0) + return (ENXIO); + adp->va_flags |= V_ADP_REGISTERED; return (0); } @@ -310,6 +316,7 @@ creator_init(int unit, video_adapter_t *adp, int flags) static int creator_get_info(video_adapter_t *adp, int mode, video_info_t *info) { + bcopy(&adp->va_info, info, sizeof(*info)); return (0); } @@ -317,8 +324,8 @@ creator_get_info(video_adapter_t *adp, int mode, video_info_t *info) static int creator_query_mode(video_adapter_t *adp, video_info_t *info) { - TODO; - return (0); + + return (ENODEV); } static int @@ -335,13 +342,6 @@ creator_set_mode(video_adapter_t *adp, int mode) creator_ras_setbg(sc, 0x0); creator_ras_setfg(sc, 0xffffff); - - creator_ras_fifo_wait(sc, 4); - FFB_WRITE(sc, FFB_FBC, FFB_FBC_BX, 0); - FFB_WRITE(sc, FFB_FBC, FFB_FBC_BY, 0); - FFB_WRITE(sc, FFB_FBC, FFB_FBC_BH, sc->sc_height); - FFB_WRITE(sc, FFB_FBC, FFB_FBC_BW, sc->sc_width); - creator_ras_wait(sc); return (0); @@ -351,101 +351,97 @@ static int creator_save_font(video_adapter_t *adp, int page, int size, u_char *data, int c, int count) { - TODO; - return (0); + + return (ENODEV); } static int creator_load_font(video_adapter_t *adp, int page, int size, u_char *data, int c, int count) { - TODO; - return (0); + + return (ENODEV); } static int creator_show_font(video_adapter_t *adp, int page) { - TODO; - return (0); + + return (ENODEV); } static int creator_save_palette(video_adapter_t *adp, u_char *palette) { - /* TODO; */ - return (0); + + return (ENODEV); } static int creator_load_palette(video_adapter_t *adp, u_char *palette) { - /* TODO; */ - return (0); + + return (ENODEV); } static int creator_set_border(video_adapter_t *adp, int border) { - /* TODO; */ + struct creator_softc *sc; + + sc = (struct creator_softc *)adp; + creator_fill_rect(adp, border, 0, 0, sc->sc_width, sc->sc_ymargin); + creator_fill_rect(adp, border, 0, sc->sc_height - sc->sc_ymargin, + sc->sc_width, sc->sc_ymargin); + creator_fill_rect(adp, border, 0, 0, sc->sc_xmargin, sc->sc_height); + creator_fill_rect(adp, border, sc->sc_width - sc->sc_xmargin, 0, + sc->sc_xmargin, sc->sc_height); return (0); } static int creator_save_state(video_adapter_t *adp, void *p, size_t size) { - TODO; - return (0); + + return (ENODEV); } static int creator_load_state(video_adapter_t *adp, void *p) { - TODO; - return (0); + + return (ENODEV); } static int creator_set_win_org(video_adapter_t *adp, off_t offset) { - TODO; - return (0); + + return (ENODEV); } static int creator_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { - struct creator_softc *sc; - sc = (struct creator_softc *)adp; - if (sc->sc_colp != NULL && sc->sc_rowp != NULL) { - *col = *sc->sc_colp; - *row = *sc->sc_rowp; - } else { - *col = 0; - *row = 0; - } + *col = 0; + *row = 0; return (0); } static int creator_set_hw_cursor(video_adapter_t *adp, int col, int row) { - struct creator_softc *sc; - sc = (struct creator_softc *)adp; - if (sc->sc_colp != NULL && sc->sc_rowp != NULL) { - *sc->sc_colp = col; - *sc->sc_rowp = row; - } - return (0); + return (ENODEV); } static int creator_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { - return (0); + + return (ENODEV); } static int @@ -455,14 +451,17 @@ creator_blank_display(video_adapter_t *adp, int mode) int v; sc = (struct creator_softc *)adp; - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, 0x6000); + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, FFB_DAC_CFG_TGEN); v = FFB_READ(sc, FFB_DAC, FFB_DAC_VALUE); - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, 0x6000); - if (mode == V_DISPLAY_ON) - v |= 0x1; + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, FFB_DAC_CFG_TGEN); + if (mode == V_DISPLAY_ON || mode == V_DISPLAY_BLANK) + v |= FFB_DAC_CFG_TGEN_VIDE; else - v &= ~0x1; + v &= ~FFB_DAC_CFG_TGEN_VIDE; FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE, v); + if (mode == V_DISPLAY_BLANK) + creator_fill_rect(adp, (SC_NORM_ATTR >> 4) & 0xf, 0, 0, + sc->sc_width, sc->sc_height); return (0); } @@ -470,72 +469,113 @@ static int creator_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr, int prot) { - TODO; - return (0); + + return (EINVAL); } static int creator_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { - TODO; + struct creator_softc *sc; + struct fbcursor *fbc; + struct fbtype *fb; + + sc = (struct creator_softc *)adp; + switch (cmd) { + case FBIOGTYPE: + fb = (struct fbtype *)data; + fb->fb_type = FBTYPE_CREATOR; + fb->fb_height = sc->sc_height; + fb->fb_width = sc->sc_width; + fb->fb_depth = fb->fb_cmsize = fb->fb_size = 0; + break; + case FBIOSCURSOR: + fbc = (struct fbcursor *)data; + if (fbc->set & FB_CUR_SETCUR) { + if (fbc->enable == 0) { + creator_cursor_enable(sc, 0); + sc->sc_flags &= ~CREATOR_CUREN; + } else + return (ENODEV); + } + break; + default: + return (fb_commonioctl(adp, cmd, data)); + } return (0); } static int creator_clear(video_adapter_t *adp) { - TODO; + return (0); } static int creator_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { - TODO; + struct creator_softc *sc; + + sc = (struct creator_softc *)adp; + creator_ras_fifo_wait(sc, 2); + FFB_WRITE(sc, FFB_FBC, FFB_FBC_ROP, FBC_ROP_NEW); + FFB_WRITE(sc, FFB_FBC, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE); + creator_ras_setfg(sc, cmap[val & 0xf]); + creator_ras_fifo_wait(sc, 4); + FFB_WRITE(sc, FFB_FBC, FFB_FBC_BX, x); + FFB_WRITE(sc, FFB_FBC, FFB_FBC_BY, y); + FFB_WRITE(sc, FFB_FBC, FFB_FBC_BW, cx); + FFB_WRITE(sc, FFB_FBC, FFB_FBC_BH, cy); + creator_ras_wait(sc); return (0); } static int creator_bitblt(video_adapter_t *adp, ...) { - TODO; + return (0); } static int creator_diag(video_adapter_t *adp, int level) { - TODO; + video_info_t info; + + fb_dump_adp_info(adp->va_name, adp, level); + creator_get_info(adp, 0, &info); + fb_dump_mode_info(adp->va_name, adp, &info, level); return (0); } static int creator_save_cursor_palette(video_adapter_t *adp, u_char *palette) { - TODO; - return (0); + + return (ENODEV); } static int creator_load_cursor_palette(video_adapter_t *adp, u_char *palette) { - TODO; - return (0); + + return (ENODEV); } static int creator_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) { - TODO; - return (0); + + return (ENODEV); } static int creator_putp(video_adapter_t *adp, vm_offset_t off, u_int32_t p, u_int32_t a, int size, int bpp, int bit_ltor, int byte_ltor) { - TODO; - return (0); + + return (ENODEV); } static int @@ -582,7 +622,12 @@ creator_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image, struct creator_softc *sc; sc = (struct creator_softc *)adp; - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, 0x104); + if (!(sc->sc_flags & CREATOR_CUREN)) { + creator_cursor_install(sc); + creator_cursor_enable(sc, 1); + sc->sc_flags |= CREATOR_CUREN; + } + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, FFB_DAC_CUR_POS); FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, ((y + sc->sc_ymargin) << 16) | (x + sc->sc_xmargin)); return (0); @@ -633,7 +678,7 @@ creator_ras_wait(struct creator_softc *sc) for (;;) { ucsr = FFB_READ(sc, FFB_FBC, FFB_FBC_UCSR); - if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0) + if ((ucsr & (FBC_UCSR_FB_BUSY | FBC_UCSR_RP_BUSY)) == 0) break; r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL); if (r != 0) { @@ -641,3 +686,37 @@ creator_ras_wait(struct creator_softc *sc) } } } + +static void +creator_cursor_enable(struct creator_softc *sc, int onoff) +{ + int v; + + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, FFB_DAC_CUR_CTRL); + if (sc->sc_flags & CREATOR_CURINV) + v = onoff ? FFB_DAC_CUR_CTRL_P0 | FFB_DAC_CUR_CTRL_P1 : 0; + else + v = onoff ? 0 : FFB_DAC_CUR_CTRL_P0 | FFB_DAC_CUR_CTRL_P1; + FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, v); +} + +static void +creator_cursor_install(struct creator_softc *sc) +{ + int i, j; + + creator_cursor_enable(sc, 0); + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, FFB_DAC_CUR_COLOR1); + FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0xffffff); + FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0x0); + for (i = 0; i < 2; i++) { + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, + i ? FFB_DAC_CUR_BITMAP_P0 : FFB_DAC_CUR_BITMAP_P1); + for (j = 0; j < 64; j++) { + FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, + *(uint32_t *)(&creator_mouse_pointer[j][0])); + FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, + *(uint32_t *)(&creator_mouse_pointer[j][4])); + } + } +} diff --git a/sys/dev/fb/creatorreg.h b/sys/dev/fb/creatorreg.h index b3be9e2ae5d3..bb8162fc0f4b 100644 --- a/sys/dev/fb/creatorreg.h +++ b/sys/dev/fb/creatorreg.h @@ -1,3 +1,25 @@ +/*- + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * from: XFree86: ffb_dac.h,v 1.1 2000/05/23 04:47:44 dawes Exp + */ /*- * Copyright (c) 2003 Jake Burkholder. * All rights reserved. @@ -37,6 +59,51 @@ #define FFB_DAC_TYPE2 0x8 #define FFB_DAC_VALUE2 0xc +/* FFB_DAC_TYPE configuration and palette register addresses */ +#define FFB_DAC_CFG_UCTRL 0x1001 /* User Control */ +#define FFB_DAC_CFG_TGEN 0x6000 /* Timing Generator Control */ +#define FFB_DAC_CFG_DID 0x8000 /* Device Identification */ + +/* FFB_DAC_CFG_UCTRL register */ +#define FFB_DAC_UCTRL_IPDISAB 0x0001 /* Input Pullup Resistor Dis. */ +#define FFB_DAC_UCTRL_ABLANK 0x0002 /* Asynchronous Blank */ +#define FFB_DAC_UCTRL_DBENAB 0x0004 /* Double-Buffer Enable */ +#define FFB_DAC_UCTRL_OVENAB 0x0008 /* Overlay Enable */ +#define FFB_DAC_UCTRL_WMODE 0x0030 /* Window Mode */ +#define FFB_DAC_UCTRL_WM_COMB 0x0000 /* Window Mode Combined */ +#define FFB_DAC_UCTRL_WM_S4 0x0010 /* Window Mode Separate 4 */ +#define FFB_DAC_UCTRL_WM_S8 0x0020 /* Window Mode Separate 8 */ +#define FFB_DAC_UCTRL_WM_RESV 0x0030 /* Window Mode Reserved */ +#define FFB_DAC_UCTRL_MANREV 0x0f00 /* Manufacturing Revision */ + +/* FFB_DAC_CFG_TGEN register */ +#define FFB_DAC_CFG_TGEN_VIDE 0x01 /* Video Enable */ +#define FFB_DAC_CFG_TGEN_TGE 0x02 /* Timing Generator Enable */ +#define FFB_DAC_CFG_TGEN_HSD 0x04 /* HSYNC* Disable */ +#define FFB_DAC_CFG_TGEN_VSD 0x08 /* VSYNC* Disable */ +#define FFB_DAC_CFG_TGEN_EQD 0x10 /* Equalization Disable */ +#define FFB_DAC_CFG_TGEN_MM 0x20 /* 0 = Slave, 1 = Master */ +#define FFB_DAC_CFG_TGEN_IM 0x40 /* 1 = Interlaced Mode */ + +/* FFB_DAC_CFG_DID register */ +#define FFB_DAC_CFG_DID_ONE 0x00000001 /* Always Set */ +#define FFB_DAC_CFG_DID_MANUF 0x00000ffe /* DAC Manufacturer ID */ +#define FFB_DAC_CFG_DID_PNUM 0x0ffff000 /* DAC Part Number */ +#define FFB_DAC_CFG_DID_REV 0xf0000000 /* DAC Revision */ + +/* FFB_DAC_TYPE2 cursor register addresses */ +#define FFB_DAC_CUR_BITMAP_P0 0x0 /* Plane 0 Cursor Bitmap */ +#define FFB_DAC_CUR_BITMAP_P1 0x80 /* Plane 1 Cursor Bitmap */ +#define FFB_DAC_CUR_CTRL 0x100 /* Cursor Control */ +#define FFB_DAC_CUR_COLOR0 0x101 /* Cursor Color 0 */ +#define FFB_DAC_CUR_COLOR1 0x102 /* Cursor Color 1 (bg) */ +#define FFB_DAC_CUR_COLOR2 0x103 /* Cursor Color 2 (fg) */ +#define FFB_DAC_CUR_POS 0x104 /* Active Cursor Position */ + +/* FFB_DAC_CUR_CTRL register (might be inverted on PAC1 DACs) */ +#define FFB_DAC_CUR_CTRL_P0 0x1 /* Plane0 Display Disable */ +#define FFB_DAC_CUR_CTRL_P1 0x2 /* Plane1 Display Disable */ + #define FFB_FBC 2 #define FFB_FBC_BY 0x60 #define FFB_FBC_BX 0x64 @@ -139,33 +206,37 @@ #define FFB_WRITE(sc, reg, off, val) \ bus_space_write_4((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off), (val)) +#define CREATOR_DRIVER_NAME "creator" + struct creator_softc { video_adapter_t sc_va; /* XXX must be first */ - struct cdev *sc_si; + phandle_t sc_node; + struct cdev *sc_si; + + int sc_rid[FFB_NREG]; struct resource *sc_reg[FFB_NREG]; bus_space_tag_t sc_bt[FFB_NREG]; bus_space_handle_t sc_bh[FFB_NREG]; - char sc_model[32]; - int sc_console; - int sc_dac; int sc_height; int sc_width; - int sc_ncol; - int sc_nrow; int sc_xmargin; int sc_ymargin; u_char *sc_font; - int *sc_rowp; - int *sc_colp; int sc_bg_cache; int sc_fg_cache; int sc_fifo_cache; + + int sc_flags; +#define CREATOR_AFB (1 << 0) +#define CREATOR_CUREN (1 << 1) +#define CREATOR_CURINV (1 << 2) +#define CREATOR_PAC1 (1 << 3) }; -#endif +#endif /* !_DEV_FB_CREATOR_H_ */ diff --git a/sys/sparc64/creator/creator.h b/sys/sparc64/creator/creator.h index b3be9e2ae5d3..bb8162fc0f4b 100644 --- a/sys/sparc64/creator/creator.h +++ b/sys/sparc64/creator/creator.h @@ -1,3 +1,25 @@ +/*- + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * from: XFree86: ffb_dac.h,v 1.1 2000/05/23 04:47:44 dawes Exp + */ /*- * Copyright (c) 2003 Jake Burkholder. * All rights reserved. @@ -37,6 +59,51 @@ #define FFB_DAC_TYPE2 0x8 #define FFB_DAC_VALUE2 0xc +/* FFB_DAC_TYPE configuration and palette register addresses */ +#define FFB_DAC_CFG_UCTRL 0x1001 /* User Control */ +#define FFB_DAC_CFG_TGEN 0x6000 /* Timing Generator Control */ +#define FFB_DAC_CFG_DID 0x8000 /* Device Identification */ + +/* FFB_DAC_CFG_UCTRL register */ +#define FFB_DAC_UCTRL_IPDISAB 0x0001 /* Input Pullup Resistor Dis. */ +#define FFB_DAC_UCTRL_ABLANK 0x0002 /* Asynchronous Blank */ +#define FFB_DAC_UCTRL_DBENAB 0x0004 /* Double-Buffer Enable */ +#define FFB_DAC_UCTRL_OVENAB 0x0008 /* Overlay Enable */ +#define FFB_DAC_UCTRL_WMODE 0x0030 /* Window Mode */ +#define FFB_DAC_UCTRL_WM_COMB 0x0000 /* Window Mode Combined */ +#define FFB_DAC_UCTRL_WM_S4 0x0010 /* Window Mode Separate 4 */ +#define FFB_DAC_UCTRL_WM_S8 0x0020 /* Window Mode Separate 8 */ +#define FFB_DAC_UCTRL_WM_RESV 0x0030 /* Window Mode Reserved */ +#define FFB_DAC_UCTRL_MANREV 0x0f00 /* Manufacturing Revision */ + +/* FFB_DAC_CFG_TGEN register */ +#define FFB_DAC_CFG_TGEN_VIDE 0x01 /* Video Enable */ +#define FFB_DAC_CFG_TGEN_TGE 0x02 /* Timing Generator Enable */ +#define FFB_DAC_CFG_TGEN_HSD 0x04 /* HSYNC* Disable */ +#define FFB_DAC_CFG_TGEN_VSD 0x08 /* VSYNC* Disable */ +#define FFB_DAC_CFG_TGEN_EQD 0x10 /* Equalization Disable */ +#define FFB_DAC_CFG_TGEN_MM 0x20 /* 0 = Slave, 1 = Master */ +#define FFB_DAC_CFG_TGEN_IM 0x40 /* 1 = Interlaced Mode */ + +/* FFB_DAC_CFG_DID register */ +#define FFB_DAC_CFG_DID_ONE 0x00000001 /* Always Set */ +#define FFB_DAC_CFG_DID_MANUF 0x00000ffe /* DAC Manufacturer ID */ +#define FFB_DAC_CFG_DID_PNUM 0x0ffff000 /* DAC Part Number */ +#define FFB_DAC_CFG_DID_REV 0xf0000000 /* DAC Revision */ + +/* FFB_DAC_TYPE2 cursor register addresses */ +#define FFB_DAC_CUR_BITMAP_P0 0x0 /* Plane 0 Cursor Bitmap */ +#define FFB_DAC_CUR_BITMAP_P1 0x80 /* Plane 1 Cursor Bitmap */ +#define FFB_DAC_CUR_CTRL 0x100 /* Cursor Control */ +#define FFB_DAC_CUR_COLOR0 0x101 /* Cursor Color 0 */ +#define FFB_DAC_CUR_COLOR1 0x102 /* Cursor Color 1 (bg) */ +#define FFB_DAC_CUR_COLOR2 0x103 /* Cursor Color 2 (fg) */ +#define FFB_DAC_CUR_POS 0x104 /* Active Cursor Position */ + +/* FFB_DAC_CUR_CTRL register (might be inverted on PAC1 DACs) */ +#define FFB_DAC_CUR_CTRL_P0 0x1 /* Plane0 Display Disable */ +#define FFB_DAC_CUR_CTRL_P1 0x2 /* Plane1 Display Disable */ + #define FFB_FBC 2 #define FFB_FBC_BY 0x60 #define FFB_FBC_BX 0x64 @@ -139,33 +206,37 @@ #define FFB_WRITE(sc, reg, off, val) \ bus_space_write_4((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off), (val)) +#define CREATOR_DRIVER_NAME "creator" + struct creator_softc { video_adapter_t sc_va; /* XXX must be first */ - struct cdev *sc_si; + phandle_t sc_node; + struct cdev *sc_si; + + int sc_rid[FFB_NREG]; struct resource *sc_reg[FFB_NREG]; bus_space_tag_t sc_bt[FFB_NREG]; bus_space_handle_t sc_bh[FFB_NREG]; - char sc_model[32]; - int sc_console; - int sc_dac; int sc_height; int sc_width; - int sc_ncol; - int sc_nrow; int sc_xmargin; int sc_ymargin; u_char *sc_font; - int *sc_rowp; - int *sc_colp; int sc_bg_cache; int sc_fg_cache; int sc_fifo_cache; + + int sc_flags; +#define CREATOR_AFB (1 << 0) +#define CREATOR_CUREN (1 << 1) +#define CREATOR_CURINV (1 << 2) +#define CREATOR_PAC1 (1 << 3) }; -#endif +#endif /* !_DEV_FB_CREATOR_H_ */ diff --git a/sys/sparc64/creator/creator_upa.c b/sys/sparc64/creator/creator_upa.c index 1541c8a65c0e..d7b1bb8d9781 100644 --- a/sys/sparc64/creator/creator_upa.c +++ b/sys/sparc64/creator/creator_upa.c @@ -22,15 +22,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include #include #include -#include #include +#include +#include #include #include #include @@ -68,7 +70,7 @@ static device_method_t creator_upa_methods[] = { }; static driver_t creator_upa_driver = { - "creator", + CREATOR_DRIVER_NAME, creator_upa_methods, sizeof(struct creator_softc), }; @@ -141,7 +143,7 @@ creator_upa_probe(device_t dev) device_set_desc(dev, "Creator"); break; case 0x3: - device_set_desc(dev, "Creator3d"); + device_set_desc(dev, "Creator3D"); break; default: return (ENXIO); @@ -150,7 +152,7 @@ creator_upa_probe(device_t dev) device_set_desc(dev, "Elite3D"); else return (ENXIO); - return (0); + return (BUS_PROBE_DEFAULT); } static int @@ -159,69 +161,106 @@ creator_upa_attach(device_t dev) struct creator_softc *sc; struct upa_regs *reg; video_switch_t *sw; - phandle_t chosen; - ihandle_t stdout; + phandle_t node; bus_addr_t phys; bus_size_t size; - phandle_t node; + int error; int nreg; int unit; - int rid; int i; - chosen = OF_finddevice("/chosen"); - OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); node = nexus_get_node(dev); - unit = device_get_unit(dev); - if (unit == 0 /*node == OF_instance_to_package(stdout)*/) { - sc = (struct creator_softc *)vid_get_adapter(0); - device_set_softc(dev, sc); + if ((sc = (struct creator_softc *)vid_get_adapter(vid_find_adapter( + CREATOR_DRIVER_NAME, 0))) != NULL && sc->sc_node == node) { + device_printf(dev, "console\n"); + device_set_softc(dev, sc); } else { sc = device_get_softc(dev); + bzero(sc, sizeof(struct creator_softc)); + sc->sc_node = node; nreg = nexus_get_nreg(dev); reg = nexus_get_reg(dev); for (i = 0; i < nreg; i++) { phys = UPA_REG_PHYS(reg + i); size = UPA_REG_SIZE(reg + i); - rid = 0; + sc->sc_rid[i] = 0; sc->sc_reg[i] = bus_alloc_resource(dev, SYS_RES_MEMORY, - &rid, phys, phys + size - 1, size, RF_ACTIVE); - if (sc->sc_reg[i] == NULL) - panic("creator_upa_attach"); + &sc->sc_rid[i], phys, phys + size - 1, size, + RF_ACTIVE); + if (sc->sc_reg[i] == NULL) { + device_printf(dev, + "cannot allocate resources\n"); + error = ENXIO; + goto fail; + } sc->sc_bt[i] = rman_get_bustag(sc->sc_reg[i]); sc->sc_bh[i] = rman_get_bushandle(sc->sc_reg[i]); } - OF_getprop(node, "height", &sc->sc_height, - sizeof(sc->sc_height)); - OF_getprop(node, "width", &sc->sc_width, - sizeof(sc->sc_width)); - sw = vid_get_switch("creator"); - sw->init(unit, &sc->sc_va, 0); + if (strcmp(nexus_get_name(dev), "SUNW,afb") == 0) + sc->sc_flags |= CREATOR_AFB; + if ((sw = vid_get_switch(CREATOR_DRIVER_NAME)) == NULL) { + device_printf(dev, "cannot get video switch\n"); + error = ENODEV; + goto fail; + } + /* + * During device configuration we don't necessarily probe + * the adapter which is the console first so we can't use + * the device unit number for the video adapter unit. The + * worst case would be that we use the video adapter unit + * 0 twice. As it doesn't really matter which unit number + * the corresponding video adapter has just use the next + * unused one. + */ + for (i = 0; i < devclass_get_maxunit(creator_upa_devclass); i++) + if (vid_find_adapter(CREATOR_DRIVER_NAME, i) < 0) + break; + if ((error = sw->init(i, &sc->sc_va, 0)) != 0) { + device_printf(dev, "cannot initialize adapter\n"); + goto fail; + } } + if (bootverbose) { + if (sc->sc_flags & CREATOR_PAC1) + device_printf(dev, + "BT9068/PAC1 RAMDAC (%s cursor control)\n", + sc->sc_flags & CREATOR_CURINV ? "inverted" : + "normal"); + else + device_printf(dev, "BT498/PAC2 RAMDAC\n"); + } + device_printf(dev, "resolution %dx%d\n", sc->sc_width, sc->sc_height); + + unit = device_get_unit(dev); sc->sc_si = make_dev(&creator_devsw, unit, UID_ROOT, GID_WHEEL, 0600, "fb%d", unit); sc->sc_si->si_drv1 = sc; - /* XXX */ - if (unit == 0) - sc_attach_unit(unit, 0); - EVENTHANDLER_REGISTER(shutdown_final, creator_shutdown, sc, SHUTDOWN_PRI_DEFAULT); return (0); + + fail: + for (i = 0; i < FFB_NREG; i++) + if (sc->sc_reg[i] != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid[i], + sc->sc_reg[i]); + return (error); } static int creator_open(struct cdev *dev, int flags, int mode, struct thread *td) { + return (0); } static int creator_close(struct cdev *dev, int flags, int mode, struct thread *td) { + return (0); } @@ -230,37 +269,9 @@ creator_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) { struct creator_softc *sc; - struct fbcursor *fbc; - struct fbtype *fb; sc = dev->si_drv1; - switch (cmd) { - case FBIOGTYPE: - fb = (struct fbtype *)data; - fb->fb_type = FBTYPE_CREATOR; - fb->fb_height = sc->sc_height; - fb->fb_width = sc->sc_width; - break; - case FBIOSCURSOR: - fbc = (struct fbcursor *)data; - switch (fbc->set) { - case FB_CUR_SETALL: - printf("creator_dev_ioctl: FB_CUR_SETALL\n"); - break; - case FB_CUR_SETCMAP: - printf("creator_dev_ioctl: FB_CUR_SETCMAP\n"); - break; - default: - printf("creator_dev_ioctl: FBIOSCURSOR %#x\n", - fbc->set); - break; - } - break; - default: - printf("creator_dev_ioctl: %#lx\n", cmd); - return (ENODEV); - } - return (0); + return ((*vidsw[sc->sc_va.va_index]->ioctl)(&sc->sc_va, cmd, data)); } static int @@ -286,6 +297,8 @@ creator_shutdown(void *v) { struct creator_softc *sc = v; - FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, 0x100); - FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0x3); + FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, FFB_DAC_CUR_CTRL); + FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, + sc->sc_flags & CREATOR_CURINV ? 0 : + FFB_DAC_CUR_CTRL_P0 | FFB_DAC_CUR_CTRL_P1); } diff --git a/sys/sparc64/sparc64/sc_machdep.c b/sys/sparc64/sparc64/sc_machdep.c index 885d25e865e7..032f793b8b51 100644 --- a/sys/sparc64/sparc64/sc_machdep.c +++ b/sys/sparc64/sparc64/sc_machdep.c @@ -22,23 +22,87 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include #include -#include -#include #include #include -#include #include -#include +#include +#include +#include + +#include + +#include +#include #include -static sc_softc_t sc_softcs[8]; +#define SC_MD_MAX 8 +#define SC_MD_FLAGS SC_AUTODETECT_KBD + +static sc_softc_t sc_softcs[SC_MD_MAX]; + +static device_identify_t sc_identify; +static device_probe_t sc_probe; +static device_attach_t sc_attach; + +static device_method_t sc_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, sc_identify), + DEVMETHOD(device_probe, sc_probe), + DEVMETHOD(device_attach, sc_attach), + + { 0, 0 } +}; + +static driver_t sc_driver = { + SC_DRIVER_NAME, + sc_methods, + 1, /* no softc */ +}; + +static devclass_t sc_devclass; + +DRIVER_MODULE(sc, nexus, sc_driver, sc_devclass, 0, 0); + +static void +sc_identify(driver_t *driver, device_t parent) +{ + + /* + * Add with a priority guaranteed to make it last on + * the device list. + */ + BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0); +} + +static int +sc_probe(device_t dev) +{ + int unit; + + unit = device_get_unit(dev); + if (strcmp(nexus_get_name(dev), SC_DRIVER_NAME) != 0 || + unit >= SC_MD_MAX) + return (ENXIO); + + device_set_desc(dev, "System console"); + return (sc_probe_unit(unit, device_get_flags(dev) | SC_MD_FLAGS)); +} + +static int +sc_attach(device_t dev) +{ + + return (sc_attach_unit(device_get_unit(dev), + device_get_flags(dev) | SC_MD_FLAGS)); +} int sc_get_cons_priority(int *unit, int *flags) @@ -52,7 +116,8 @@ sc_get_cons_priority(int *unit, int *flags) int sc_max_unit(void) { - return (1); + + return (devclass_get_maxunit(sc_devclass)); } sc_softc_t * @@ -60,7 +125,7 @@ sc_get_softc(int unit, int flags) { sc_softc_t *sc; - if (unit < 0) + if (unit < 0 || unit >= SC_MD_MAX) return (NULL); sc = &sc_softcs[unit]; sc->unit = unit; @@ -76,10 +141,12 @@ sc_get_softc(int unit, int flags) void sc_get_bios_values(bios_values_t *values) { + } int sc_tone(int hz) { + return (0); }