diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2007-12-09 21:54:01 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2007-12-09 21:54:01 +0000 |
commit | abc348f43f672247cd1416c55a4504b4cad2f991 (patch) | |
tree | 7528727d712d62c87c31af6c56bc1fda3b7cd725 | |
parent | 8fa549358cd894ca554b22c6d76d2272ad08a3dc (diff) |
Attach lcspx to SPX option boards on VAXstation 3100. Tested on model 38 (KA42)
only, should work on model 76 (KA43) as well.
-rw-r--r-- | share/man/man4/man4.vax/lcspx.4 | 12 | ||||
-rw-r--r-- | sys/arch/vax/vsa/lcspx.c | 220 |
2 files changed, 196 insertions, 36 deletions
diff --git a/share/man/man4/man4.vax/lcspx.4 b/share/man/man4/man4.vax/lcspx.4 index 82c6acb8ddc..03e6cef49f3 100644 --- a/share/man/man4/man4.vax/lcspx.4 +++ b/share/man/man4/man4.vax/lcspx.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: lcspx.4,v 1.3 2007/05/31 19:19:57 jmc Exp $ +.\" $OpenBSD: lcspx.4,v 1.4 2007/12/09 21:53:58 miod Exp $ .\" .\" Copyright (c) 2003 Jason L. Wright (jason@thought.net) .\" All rights reserved. @@ -24,21 +24,23 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: May 31 2007 $ +.Dd $Mdocdate: December 9 2007 $ .Dt LCSPX 4 vax .Os .Sh NAME .Nm lcspx .Nd Low-Cost SPX color frame buffer .Sh SYNOPSIS -.Cd "lcspx0 at vsbus0 csr 0x39302000 " Pq "VAXstation 4000/90" +.Cd "lcspx0 at vsbus0 csr 0x39302000 " Pq "VAXstation 3100 and 4000/90" .Cd "lcspx0 at vxtbus0 " Pq "VXT2000" .Cd "wsdisplay* at lcspx?" .Sh DESCRIPTION The .Nm -is a 8 bit color frame buffer commonly encountered in VAXstation 4000/90 -systems and VXT2000 terminals. +is a 8 bit color frame buffer commonly encountered in VAXstation 3100 model 76 +and VAXstation 4000/90 systems, as well as VXT2000 terminals. +It is also available as an option for VAXstation 3100 models 20, 28, 30 and 38 +systems. .Pp The .Nm diff --git a/sys/arch/vax/vsa/lcspx.c b/sys/arch/vax/vsa/lcspx.c index 818557f6837..508ccfd4942 100644 --- a/sys/arch/vax/vsa/lcspx.c +++ b/sys/arch/vax/vsa/lcspx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lcspx.c,v 1.12 2007/10/01 16:11:19 krw Exp $ */ +/* $OpenBSD: lcspx.c,v 1.13 2007/12/09 21:54:00 miod Exp $ */ /* * Copyright (c) 2006 Miodrag Vallat. * @@ -58,6 +58,7 @@ #include <machine/scb.h> #include <machine/sid.h> #include <machine/cpu.h> +#include <machine/ka420.h> #include <uvm/uvm_extern.h> @@ -69,6 +70,10 @@ #include <dev/ic/bt463reg.h> /* actually it's a 459 here... */ +#define GPXADDR 0x3c000000 /* XXX */ +#define GPX_ADDER_OFFSET 0x0000 /* XXX */ +#include <vax/qbus/qdreg.h> /* XXX */ + #define LCSPX_REG_ADDR 0x39302000 /* registers */ #define LCSPX_REG_SIZE 0x2000 #define LCSPX_REG1_ADDR 0x39b00000 /* more registers */ @@ -76,16 +81,13 @@ #define LCSPX_RAMDAC_INTERLEAVE 0x00004000 #define LCSPX_FB_ADDR 0x38000000 /* frame buffer */ -#define LCSPX_WIDTH 1280 -#define LCSPX_HEIGHT 1024 -#define LCSPX_FBSIZE (LCSPX_WIDTH * LCSPX_HEIGHT) - void lcspx_attach(struct device *, struct device *, void *); int lcspx_vsbus_match(struct device *, void *, void *); int lcspx_vxtbus_match(struct device *, void *, void *); struct lcspx_screen { struct rasops_info ss_ri; + u_int ss_fbsize; caddr_t ss_addr; /* frame buffer address */ volatile u_int8_t *ss_ramdac[4]; vaddr_t ss_reg; @@ -157,18 +159,57 @@ int lcspx_putcmap(struct lcspx_screen *, struct wsdisplay_cmap *); static __inline__ void lcspx_ramdac_wraddr(struct lcspx_screen *, u_int); void lcspx_resetcmap(struct lcspx_screen *); -int lcspx_setup_screen(struct lcspx_screen *); +int lcspx_setup_screen(struct lcspx_screen *, u_int, u_int); int lcspx_vsbus_match(struct device *parent, void *vcf, void *aux) { + extern int oldvsbus; struct vsbus_softc *sc = (void *)parent; struct vsbus_attach_args *va = aux; + volatile struct adder *adder; + u_short status; switch (vax_boardtype) { default: return (0); + case VAX_BTYP_410: + case VAX_BTYP_420: + case VAX_BTYP_43: + if (va->va_paddr != LCSPX_REG_ADDR) + return (0); + + /* not present on microvaxes */ + if ((vax_confdata & KA420_CFG_MULTU) != 0) + return (0); + + if ((vax_confdata & KA420_CFG_VIDOPT) == 0) + return (0); + + /* + * We can not check for video memory at the SPX address, + * because if no SPX board is installed, the probe will + * just hang. + * Instead, check for a GPX board and skip probe if the + * video option really is a GPX. + */ + adder = (volatile struct adder *) + vax_map_physmem(GPXADDR + GPX_ADDER_OFFSET, 1); + if (adder == NULL) + return (0); + adder->status = 0; + status = adder->status; + vax_unmap_physmem((vaddr_t)adder, 1); + if (status != offsetof(struct adder, status)) + return (0); + + /* XXX do not attach if not console... yet */ + if ((vax_confdata & KA420_CFG_L3CON) != 0) + return (0); + + break; + case VAX_BTYP_49: if (va->va_paddr != LCSPX_REG_ADDR) return (0); @@ -180,7 +221,7 @@ lcspx_vsbus_match(struct device *parent, void *vcf, void *aux) } sc->sc_mask = 0x04; /* XXX - should be generated */ - scb_fake(0x120, 0x15); + scb_fake(0x120, oldvsbus ? 0x14 : 0x15); return (20); } @@ -219,13 +260,25 @@ lcspx_attach(struct device *parent, struct device *self, void *aux) struct lcspx_screen *ss; struct wsemuldisplaydev_attach_args aa; int i, console; + vaddr_t reg1; + u_int32_t magic; + u_int width, height; extern struct consdev wsdisplay_cons; if (cn_tab == &wsdisplay_cons) { - if (vax_boardtype == VAX_BTYP_49) + switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_420: + case VAX_BTYP_43: + console = (vax_confdata & KA420_CFG_L3CON) == 0; + break; + case VAX_BTYP_49: console = (vax_confdata & 8) == 0; - else /* VXT2000 */ + break; + default: /* VXT2000 */ console = (vax_confdata & 2) != 0; + break; + } } else console = 0; if (console) { @@ -238,18 +291,42 @@ lcspx_attach(struct device *parent, struct device *self, void *aux) return; } - ss->ss_addr = (caddr_t)vax_map_physmem(LCSPX_FB_ADDR, - LCSPX_FBSIZE / VAX_NBPG); - if (ss->ss_addr == NULL) { - printf(": can not map frame buffer\n"); - goto fail1; + switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_420: + case VAX_BTYP_43: + /* + * See ``EVIL KLUGE ALERT!'' comments in + * lcspxcninit() at the end of this file + * for meaningless details. + */ + reg1 = vax_map_physmem(LCSPX_REG1_ADDR, 1); + if (reg1 == 0L) { + printf(": can not map registers\n"); + goto fail1; + } + magic = *(u_int32_t *)(reg1 + 0x11c); + vax_unmap_physmem(reg1, 1); + + if (magic & 0x80) { + width = 1280; + height = 1024; + } else { + width = 1024; + height = 864; + } + break; + default: + width = 1280; + height = 1024; + break; } ss->ss_reg = vax_map_physmem(LCSPX_REG_ADDR, LCSPX_REG_SIZE / VAX_NBPG); if (ss->ss_reg == 0L) { printf(": can not map registers\n"); - goto fail2; + goto fail1; } for (i = 0; i < 4; i++) { @@ -257,18 +334,27 @@ lcspx_attach(struct device *parent, struct device *self, void *aux) LCSPX_RAMDAC_ADDR + i * LCSPX_RAMDAC_INTERLEAVE, 1); if (ss->ss_ramdac[i] == NULL) { printf(": can not map RAMDAC registers\n"); - goto fail3; + goto fail2; } } - if (lcspx_setup_screen(ss) != 0) { + ss->ss_fbsize = width * height; + ss->ss_addr = (caddr_t)vax_map_physmem(LCSPX_FB_ADDR, + ss->ss_fbsize / VAX_NBPG); + if (ss->ss_addr == NULL) { + printf(": can not map frame buffer\n"); + goto fail3; + } + + if (lcspx_setup_screen(ss, width, height) != 0) { printf(": initialization failed\n"); goto fail3; } } sc->sc_scr = ss; - printf("\n%s: 1280x1024x8 frame buffer\n", self->dv_xname); + printf("\n%s: %dx%dx8 frame buffer\n", self->dv_xname, + ss->ss_ri.ri_width, ss->ss_ri.ri_height); aa.console = console; aa.scrdata = &lcspx_screenlist; @@ -280,12 +366,12 @@ lcspx_attach(struct device *parent, struct device *self, void *aux) return; fail3: + vax_unmap_physmem((vaddr_t)ss->ss_addr, ss->ss_fbsize / VAX_NBPG); +fail2: for (i = 0; i < 4; i++) if (ss->ss_ramdac[i] != NULL) vax_unmap_physmem((vaddr_t)ss->ss_ramdac[i], 1); vax_unmap_physmem(ss->ss_reg, LCSPX_REG_SIZE / VAX_NBPG); -fail2: - vax_unmap_physmem((vaddr_t)ss->ss_addr, LCSPX_FBSIZE / VAX_NBPG); fail1: free(ss, M_DEVBUF); } @@ -302,15 +388,15 @@ lcspx_ramdac_wraddr(struct lcspx_screen *ss, u_int addr) * pick a font, initialize a rasops structure, setup the accessops callbacks.) */ int -lcspx_setup_screen(struct lcspx_screen *ss) +lcspx_setup_screen(struct lcspx_screen *ss, u_int width, u_int height) { struct rasops_info *ri = &ss->ss_ri; bzero(ri, sizeof(*ri)); ri->ri_depth = 8; - ri->ri_width = LCSPX_WIDTH; - ri->ri_height = LCSPX_HEIGHT; - ri->ri_stride = LCSPX_WIDTH; + ri->ri_width = width; + ri->ri_height = height; + ri->ri_stride = width; ri->ri_flg = RI_CLEAR | RI_CENTER; ri->ri_bits = (void *)ss->ss_addr; ri->ri_hw = ss; @@ -358,8 +444,8 @@ lcspx_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) case WSDISPLAYIO_GINFO: wdf = (struct wsdisplay_fbinfo *)data; - wdf->height = LCSPX_HEIGHT; - wdf->width = LCSPX_WIDTH; + wdf->height = ss->ss_ri.ri_height; + wdf->width = ss->ss_ri.ri_width; wdf->depth = 8; wdf->cmsize = 256; break; @@ -396,7 +482,10 @@ lcspx_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) paddr_t lcspx_mmap(void *v, off_t offset, int prot) { - if (offset >= LCSPX_FBSIZE || offset < 0) + struct lcspx_softc *sc = v; + struct lcspx_screen *ss = sc->sc_scr; + + if (offset >= ss->ss_fbsize || offset < 0) return (-1); return (LCSPX_FB_ADDR + offset) >> PGSHIFT; @@ -539,15 +628,44 @@ int lcspxcnprobe() { extern vaddr_t virtual_avail; + volatile struct adder *adder; volatile u_int8_t *ch; switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_420: + case VAX_BTYP_43: + if ((vax_confdata & KA420_CFG_L3CON) != 0) + break; /* doesn't use graphics console */ + + /* not present on microvaxes */ + if ((vax_confdata & KA420_CFG_MULTU) != 0) + break; + + if ((vax_confdata & KA420_CFG_VIDOPT) == 0) + break; + + /* + * We can not check for video memory at the SPX address, + * because if no SPX board is installed, the probe will + * just hang. + * Instead, check for a GPX board and skip probe if the + * video option really is a GPX. + */ + ioaccess(virtual_avail, GPXADDR + GPX_ADDER_OFFSET, 1); + adder = (volatile struct adder *)virtual_avail; + adder->status = 0; + if (adder->status != offsetof(struct adder, status)) + break; + + return (1); + case VAX_BTYP_49: if ((vax_confdata & 8) != 0) break; /* doesn't use graphics console */ if ((vax_confdata & 0x12) != 0x02) - return (0); + break; return (1); @@ -587,12 +705,52 @@ lcspxcninit() struct lcspx_screen *ss = &lcspx_consscr; extern vaddr_t virtual_avail; int i; + u_int width, height; + vaddr_t reg1; + u_int32_t magic; long defattr; struct rasops_info *ri; + switch (vax_boardtype) { + case VAX_BTYP_410: + case VAX_BTYP_420: + case VAX_BTYP_43: + /* + * XXX EVIL KLUGE ALERT! + * + * The spx jumper settings do not show up in vax_confdata. + * I don't know which spx register sports their values, + * but I have noticed that, after the ROM has initialized + * the board, bit 0x80 at 39b0011c will reflect the + * resolution setting. + * + * This register is not read-only, so one could DEPOSIT + * a bogus value in it from the console before starting + * OpenBSD. If you do this, you deserve to be bitten + * if things go wrong. + */ + reg1 = virtual_avail; + ioaccess(reg1, LCSPX_REG1_ADDR, 1); + magic = *(u_int32_t *)(reg1 + 0x11c); + + if (magic & 0x80) { + width = 1280; + height = 1024; + } else { + width = 1024; + height = 864; + } + break; + default: + width = 1280; + height = 1024; + break; + } + + ss->ss_fbsize = width * height; ss->ss_addr = (caddr_t)virtual_avail; - virtual_avail += LCSPX_FBSIZE; - ioaccess((vaddr_t)ss->ss_addr, LCSPX_FB_ADDR, LCSPX_FBSIZE / VAX_NBPG); + virtual_avail += ss->ss_fbsize; + ioaccess((vaddr_t)ss->ss_addr, LCSPX_FB_ADDR, ss->ss_fbsize / VAX_NBPG); ss->ss_reg = virtual_avail; virtual_avail += LCSPX_REG_SIZE; @@ -608,7 +766,7 @@ lcspxcninit() virtual_avail = round_page(virtual_avail); /* this had better not fail as we can't recover there */ - if (lcspx_setup_screen(ss) != 0) + if (lcspx_setup_screen(ss, width, height) != 0) panic(__func__); ri = &ss->ss_ri; |