#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/buf.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/tgareg.h>
#include <dev/pci/tgavar.h>
#include <dev/ic/bt463reg.h>
#include <dev/ic/bt463var.h>
#include <dev/wscons/wsconsio.h>
void bt463_init(struct ramdac_cookie *);
int bt463_set_cmap(struct ramdac_cookie *,
struct wsdisplay_cmap *);
int bt463_get_cmap(struct ramdac_cookie *,
struct wsdisplay_cmap *);
int bt463_set_cursor(struct ramdac_cookie *,
struct wsdisplay_cursor *);
int bt463_get_cursor(struct ramdac_cookie *,
struct wsdisplay_cursor *);
int bt463_set_curpos(struct ramdac_cookie *,
struct wsdisplay_curpos *);
int bt463_get_curpos(struct ramdac_cookie *,
struct wsdisplay_curpos *);
int bt463_get_curmax(struct ramdac_cookie *,
struct wsdisplay_curpos *);
int bt463_check_curcmap(struct ramdac_cookie *,
struct wsdisplay_cursor *cursorp);
void bt463_set_curcmap(struct ramdac_cookie *,
struct wsdisplay_cursor *cursorp);
int bt463_get_curcmap(struct ramdac_cookie *,
struct wsdisplay_cursor *cursorp);
#ifdef BT463_DEBUG
int bt463_store(void *);
int bt463_debug(void *);
int bt463_readback(void *);
void bt463_copyback(void *);
#endif
struct ramdac_funcs bt463_funcsstruct = {
"Bt463",
bt463_register,
bt463_init,
bt463_set_cmap,
bt463_get_cmap,
bt463_set_cursor,
bt463_get_cursor,
bt463_set_curpos,
bt463_get_curpos,
bt463_get_curmax,
bt463_check_curcmap,
bt463_set_curcmap,
bt463_get_curcmap,
NULL,
};
struct bt463data {
void *cookie;
int (*ramdac_sched_update)(void *, void (*)(void *));
void (*ramdac_wr)(void *, u_int, u_int8_t);
u_int8_t (*ramdac_rd)(void *, u_int);
int changed;
char curcmap_r[2];
char curcmap_g[2];
char curcmap_b[2];
char cmap_r[BT463_NCMAP_ENTRIES];
char cmap_g[BT463_NCMAP_ENTRIES];
char cmap_b[BT463_NCMAP_ENTRIES];
int window_type[16];
};
static struct bt463data *console_data;
#define BTWREG(data, addr, val) do { bt463_wraddr((data), (addr)); \
(data)->ramdac_wr((data)->cookie, BT463_REG_IREG_DATA, (val)); } while (0)
#define BTWNREG(data, val) (data)->ramdac_wr((data)->cookie, \
BT463_REG_IREG_DATA, (val))
#define BTRREG(data, addr) (bt463_wraddr((data), (addr)), \
(data)->ramdac_rd((data)->cookie, BT463_REG_IREG_DATA))
#define BTRNREG(data) ((data)->ramdac_rd((data)->cookie, BT463_REG_IREG_DATA))
#define DATA_CURCMAP_CHANGED 0x01
#define DATA_CMAP_CHANGED 0x02
#define DATA_WTYPE_CHANGED 0x04
#define DATA_ALL_CHANGED 0x07
inline void bt463_wraddr(struct bt463data *, u_int16_t);
void bt463_update(void *);
struct ramdac_funcs *
bt463_funcs(void)
{
return &bt463_funcsstruct;
}
struct ramdac_cookie *
bt463_register(void *v, int (*sched_update)(void *, void (*)(void *)),
void (*wr)(void *, u_int, u_int8_t), u_int8_t (*rd)(void *, u_int))
{
struct bt463data *data;
data = malloc(sizeof *data, M_DEVBUF, M_WAITOK);
data->cookie = v;
data->ramdac_sched_update = sched_update;
data->ramdac_wr = wr;
data->ramdac_rd = rd;
return (struct ramdac_cookie *)data;
}
void
bt463_cninit(void *v, int (*sched_update)(void *, void (*)(void *)),
void (*wr)(void *, u_int, u_int8_t), u_int8_t (*rd)(void *, u_int))
{
struct bt463data tmp, *data = &tmp;
data->cookie = v;
data->ramdac_sched_update = sched_update;
data->ramdac_wr = wr;
data->ramdac_rd = rd;
console_data = data;
bt463_init((struct ramdac_cookie *)data);
console_data = NULL;
}
void
bt463_init(struct ramdac_cookie *rc)
{
struct bt463data *data = (struct bt463data *)rc;
int i;
BTWREG(data, BT463_IREG_COMMAND_0, 0x40);
BTWREG(data, BT463_IREG_COMMAND_1, 0x48);
BTWREG(data, BT463_IREG_COMMAND_2, 0xC0);
bt463_wraddr(data, BT463_IREG_READ_MASK_P0_P7);
for (i = 0; i < 4; i++)
BTWNREG(data, 0xff);
bt463_wraddr(data, BT463_IREG_BLINK_MASK_P0_P7);
for (i = 0; i < 4; i++)
BTWNREG(data, 0);
BTWREG(data, BT463_IREG_TEST, 0);
data->changed = DATA_ALL_CHANGED;
data->curcmap_r[0] = data->curcmap_g[0] = data->curcmap_b[0] = 0;
data->curcmap_r[1] = data->curcmap_g[1] = data->curcmap_b[1] = 0xff;
data->cmap_r[0] = data->cmap_g[0] = data->cmap_b[0] = 0;
for (i = 1; i < 256; i++) {
data->cmap_r[i] = rasops_cmap[3*i + 0];
data->cmap_g[i] = rasops_cmap[3*i + 1];
data->cmap_b[i] = rasops_cmap[3*i + 2];
}
data->window_type[0] = 0x81e100;
data->window_type[1] = 0x01e310;
for (i = 2; i < BT463_NWTYPE_ENTRIES; i++) {
data->window_type[i] = 0x81e100;
}
data->ramdac_sched_update(data->cookie, bt463_update);
}
int
bt463_set_cmap(struct ramdac_cookie *rc, struct wsdisplay_cmap *cmapp)
{
struct bt463data *data = (struct bt463data *)rc;
u_int count, index;
int s, error;
index = cmapp->index;
count = cmapp->count;
if (index >= BT463_NCMAP_ENTRIES || count > BT463_NCMAP_ENTRIES - index)
return (EINVAL);
s = spltty();
if ((error = copyin(cmapp->red, &data->cmap_r[index], count)) != 0) {
splx(s);
return (error);
}
if ((error = copyin(cmapp->green, &data->cmap_g[index], count)) != 0) {
splx(s);
return (error);
}
if ((error = copyin(cmapp->blue, &data->cmap_b[index], count)) != 0) {
splx(s);
return (error);
}
data->changed |= DATA_CMAP_CHANGED;
data->ramdac_sched_update(data->cookie, bt463_update);
splx(s);
return (0);
}
int
bt463_get_cmap(struct ramdac_cookie *rc, struct wsdisplay_cmap *cmapp)
{
struct bt463data *data = (struct bt463data *)rc;
u_int count, index;
int error;
count = cmapp->count;
index = cmapp->index;
if (index >= BT463_NCMAP_ENTRIES || count > BT463_NCMAP_ENTRIES - index)
return (EINVAL);
error = copyout(&data->cmap_r[index], cmapp->red, count);
if (error)
return (error);
error = copyout(&data->cmap_g[index], cmapp->green, count);
if (error)
return (error);
error = copyout(&data->cmap_b[index], cmapp->blue, count);
return (error);
}
int
bt463_check_curcmap(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
{
u_int index, count;
u_int8_t spare[2];
int error;
index = cursorp->cmap.index;
count = cursorp->cmap.count;
if (index >= 2 || count > 2 - index)
return (EINVAL);
if ((error = copyin(&cursorp->cmap.red, &spare, count)) != 0)
return (error);
if ((error = copyin(&cursorp->cmap.green, &spare, count)) != 0)
return (error);
if ((error = copyin(&cursorp->cmap.blue, &spare, count)) != 0)
return (error);
return (0);
}
void
bt463_set_curcmap(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
{
struct bt463data *data = (struct bt463data *)rc;
int count, index;
count = cursorp->cmap.count;
index = cursorp->cmap.index;
copyin(cursorp->cmap.red, &data->curcmap_r[index], count);
copyin(cursorp->cmap.green, &data->curcmap_g[index], count);
copyin(cursorp->cmap.blue, &data->curcmap_b[index], count);
data->changed |= DATA_CURCMAP_CHANGED;
data->ramdac_sched_update(data->cookie, bt463_update);
}
int
bt463_get_curcmap(struct ramdac_cookie *rc, struct wsdisplay_cursor *cursorp)
{
struct bt463data *data = (struct bt463data *)rc;
int error;
cursorp->cmap.index = 0;
cursorp->cmap.count = 2;
if (cursorp->cmap.red != NULL) {
error = copyout(data->curcmap_r, cursorp->cmap.red, 2);
if (error)
return (error);
}
if (cursorp->cmap.green != NULL) {
error = copyout(data->curcmap_g, cursorp->cmap.green, 2);
if (error)
return (error);
}
if (cursorp->cmap.blue != NULL) {
error = copyout(data->curcmap_b, cursorp->cmap.blue, 2);
if (error)
return (error);
}
return (0);
}
#ifdef BT463_DEBUG
int
bt463_store(void *v)
{
struct bt463data *data = (struct bt463data *)v;
data->changed = DATA_ALL_CHANGED;
data->ramdac_sched_update(data->cookie, bt463_update);
printf("Scheduled bt463 store\n");
return 0;
}
int
bt463_readback(void *v)
{
struct bt463data *data = (struct bt463data *)v;
data->ramdac_sched_update(data->cookie, bt463_copyback);
printf("Scheduled bt463 copyback\n");
return 0;
}
int
bt463_debug(void *v)
{
struct bt463data *data = (struct bt463data *)v;
int i;
u_int8_t val;
printf("BT463 main regs:\n");
for (i = 0x200; i < 0x20F; i ++) {
val = BTRREG(data, i);
printf(" $%04x %02x\n", i, val);
}
printf("BT463 revision register:\n");
val = BTRREG(data, 0x220);
printf(" $%04x %02x\n", 0x220, val);
printf("BT463 window type table (from softc):\n");
for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
printf("%02x %06x\n", i, data->window_type[i]);
}
return 0;
}
void
bt463_copyback(void *p)
{
struct bt463data *data = (struct bt463data *)p;
int i;
for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
bt463_wraddr(data, BT463_IREG_WINDOW_TYPE_TABLE + i);
data->window_type[i] = (BTRNREG(data) & 0xff);
data->window_type[i] |= (BTRNREG(data) & 0xff) << 8;
data->window_type[i] |= (BTRNREG(data) & 0xff) << 16;
}
}
#endif
inline void
bt463_wraddr(struct bt463data *data, u_int16_t ireg)
{
data->ramdac_wr(data->cookie, BT463_REG_ADDR_LOW, ireg & 0xff);
data->ramdac_wr(data->cookie, BT463_REG_ADDR_HIGH, (ireg >> 8) & 0xff);
}
void
bt463_update(void *p)
{
struct bt463data *data = (struct bt463data *)p;
int i, v;
if (console_data != NULL) {
data = console_data;
}
v = data->changed;
if (v & DATA_WTYPE_CHANGED) {
for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
bt463_wraddr(data, BT463_IREG_WINDOW_TYPE_TABLE + i);
BTWNREG(data, (data->window_type[i]) & 0xff);
BTWNREG(data, (data->window_type[i] >> 8) & 0xff);
BTWNREG(data, (data->window_type[i] >> 16) & 0xff);
}
}
if (v & DATA_CURCMAP_CHANGED) {
bt463_wraddr(data, BT463_IREG_CURSOR_COLOR_0);
for (i = 0; i < 2; i++) {
BTWNREG(data, data->curcmap_r[i]);
BTWNREG(data, data->curcmap_g[i]);
BTWNREG(data, data->curcmap_b[i]);
}
}
if (v & DATA_CMAP_CHANGED) {
bt463_wraddr(data, BT463_IREG_CPALETTE_RAM);
for (i = 0; i < BT463_NCMAP_ENTRIES; i++) {
data->ramdac_wr(data->cookie, BT463_REG_CMAP_DATA,
data->cmap_r[i]);
data->ramdac_wr(data->cookie, BT463_REG_CMAP_DATA,
data->cmap_g[i]);
data->ramdac_wr(data->cookie, BT463_REG_CMAP_DATA,
data->cmap_b[i]);
}
}
data->changed = 0;
}
int
bt463_set_cursor(struct ramdac_cookie *rc, struct wsdisplay_cursor *cur)
{
struct bt463data *data = (struct bt463data *)rc;
return tga_builtin_set_cursor(data->cookie, cur);
}
int
bt463_get_cursor(struct ramdac_cookie *rc, struct wsdisplay_cursor *cur)
{
struct bt463data *data = (struct bt463data *)rc;
return tga_builtin_get_cursor(data->cookie, cur);
}
int
bt463_set_curpos(struct ramdac_cookie *rc, struct wsdisplay_curpos *cur)
{
struct bt463data *data = (struct bt463data *)rc;
return tga_builtin_set_curpos(data->cookie, cur);
}
int
bt463_get_curpos(struct ramdac_cookie *rc, struct wsdisplay_curpos *cur)
{
struct bt463data *data = (struct bt463data *)rc;
return tga_builtin_get_curpos(data->cookie, cur);
}
int
bt463_get_curmax(struct ramdac_cookie *rc, struct wsdisplay_curpos *cur)
{
struct bt463data *data = (struct bt463data *)rc;
return tga_builtin_get_curmax(data->cookie, cur);
}