o creator(4):

- Use register macros instead of magic values in the code. [1]
  - Check the return values of OF_getprop() and other stuff that actually
    can fail.
  - Let the unimplemented video driver methods return ENODEV rather
    than 0 so other code isn't tricked into thinking a certain operation
    was successfull. In case of e.g. the video driver creator_ioctl()
    this caused vidcontrol(1) to return random garbage information.
    Remove the TODO macros in the unimplemented video driver methods
    which did a printf("%s: unimplemented\n", __func__). Under certain
    circumstances these managed to invoke a printf() when a low-level
    console device wasn't attached, yet, causing a Fast Data Access MMU
    Miss. These macros were only really usefull for development anyway.
  - Set the struct video_adapter and struct video_info va_flags and
    vi_flags etc. as appropriate.
  - In creator_configure() don't rely on hitting the node which is the
    chosen console device first when searching the OFW tree for adapters
    compatible with this driver. Instead just check whether the chosen
    console device is a viable target for this driver. Targets that are
    not the console (including additional cards in multi-head configs)
    will be attached through creator_upa_attach(). I think this how the
    code in creator_configure() was actually meant to work.
    Honour the VIO_PROBE_ONLY flag and don't initialise and register the
    console device twice when creator_configure() is called a second time
    during sc_probe_unit().
    Let creator_configure() return the number of the found adapters,
    i.e. 1 in case probing succeeds, as it's expected. The return values
    of video adapter configure functions however currently aren't checked
    so this doesn't make a difference at the moment.
  - In creator_upa_attach() don't rely on probing and attaching the
    adapter which is the console first, in case there are multiple
    adpaters and one of them is the console this could lead into using
    the video adapter unit 0 twice.
  - Make the check for DACs with inverted cursor control a bit more
    precise and actually honour that information when turning the cursor
    on or off. Add a helper function creator_cursor_enable() for this
    in order to keep code duplication low. [1]
  - Don't bother with faking a hardware cursor in case a device is the
    console. Apparently this was meant to start kernel output right after
    where the firmware left. In general this isn't worth the fuzz and
    also had no real effect as creator_set_mode() did clear the screen
    in any case, not just in case a device was not the console.
  - Implement creator_fill_rect() and use it to actually blank the
    display in creator_blank_display() when the mode is V_DISPLAY_BLANK,
    moving blanking the display out of creator_set_mode(). Use it also
    to implement creator_set_border() so the border can be re-drawn
    when switching to a VTY from X, exiting X, etc. (which leaves us
    with a black border most of the time).
  - Implement the video driver creator_ioctl(), moving the implementation
    of the IOCTL interface from the fbN CDEV version of creator_ioctl()
    into the video driver version and use the latter to implement the
    former. Use fb_commonioctl() to handle most of the FBIO IOCTLs.
    This gives programs like vidcontrol(1) which use the video driver
    creator_ioctl() a chance of working.
    Implement turning off the cursor via the FBIOSCURSOR IOCTL, which
    Xorg uses to in order to inform the OS that it's taking over the
    cursor. In creator_putm() check whether the cursor is enabled and
    (re-)install it if necessary, moving installing the cursor out of
    creator_init() and into a helper function creator_cursor_install().
    This fixes the missing mouse pointer when switching to a VTY from X,
    exiting X, etc.
  - Some clean-up (remove unused/useless code, etc.).

o sparc64/creator/creator_upa.c / sparc64/sparc64/sc_machdep.c:
  - Attach syscons(4) as an own pseudo-device on the nexus rather than
    directly in creator_upa_attach(), similiar to attaching syscons(4)
    as a pseudo-device on isa(4) on other archs. This makes it a whole
    lot easier to do the right thing in multi-head configs, especially
    with different types of graphics adapters. [2]
  - Set SC_AUTODETECT_KBD by default so USB keyboards work out of the
    box. [2]

Based on/obtained from:	Xorg 'ffb' driver [1]
Based on/obtained from:	FreeBSD/powerpc [2]
This commit is contained in:
marius 2005-05-21 20:38:26 +00:00
parent 11bd45d403
commit 494f0cf7a2
5 changed files with 549 additions and 248 deletions

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/fbio.h>
#include <sys/consio.h>
#include <sys/fbio.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <machine/ofw_upa.h>
#include <sys/rman.h>
#include <machine/sc_machdep.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/gallant12x22.h>
@ -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]));
}
}
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/consio.h>
#include <sys/conf.h>
#include <sys/consio.h>
#include <sys/eventhandler.h>
#include <sys/fbio.h>
#include <sys/kernel.h>
#include <sys/module.h>
@ -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);
}

View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/kbio.h>
#include <sys/consio.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/module.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
#include <machine/nexusvar.h>
#include <dev/syscons/syscons.h>
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);
}