diff options
| author | drochner <drochner@NetBSD.org> | 1998-05-28 16:51:50 +0000 |
|---|---|---|
| committer | drochner <drochner@NetBSD.org> | 1998-05-28 16:51:50 +0000 |
| commit | 196bb746eb2472cd85cf6d958e10d5d30cebbb6a (patch) | |
| tree | 8f3ce120e6bd7f9bf144dedef0e8e2d896023249 /sys/dev | |
| parent | b84dbbb37c467458ff7e588fd2698636b93b904e (diff) | |
Add a graphics device driver for wscons which supports legacy PC display
adapters. (minimal functionality - no virtual screens, no colors)
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/isa/files.isa | 7 | ||||
| -rw-r--r-- | sys/dev/isa/pcdisplay.c | 422 | ||||
| -rw-r--r-- | sys/dev/isa/pcdisplayvar.h | 35 |
3 files changed, 463 insertions, 1 deletions
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa index 8b0f84f0992..31fb3475336 100644 --- a/sys/dev/isa/files.isa +++ b/sys/dev/isa/files.isa @@ -1,4 +1,4 @@ -# $NetBSD: files.isa,v 1.59 1998/05/20 16:19:42 augustss Exp $ +# $NetBSD: files.isa,v 1.60 1998/05/28 16:51:50 drochner Exp $ # # Config file and device description for machine-independent ISA code. # Included by ports that need it. Requires that the SCSI files be @@ -307,6 +307,11 @@ file dev/isa/pckbc.c pckbc needs-flag attach vga at isa with vga_isa file dev/isa/vga_isa.c vga_isa needs-flag +# generic PC graphics adapter (MGA, CGA, ...) +device pcdisplay: wsemuldisplaydev, pcdisplayops +attach pcdisplay at isa +file dev/isa/pcdisplay.c pcdisplay needs-flag + # PC PPI + TIMER 1 (speaker interface) device pcppi {} attach pcppi at isa diff --git a/sys/dev/isa/pcdisplay.c b/sys/dev/isa/pcdisplay.c new file mode 100644 index 00000000000..f2e134446ec --- /dev/null +++ b/sys/dev/isa/pcdisplay.c @@ -0,0 +1,422 @@ +/* $NetBSD: pcdisplay.c,v 1.1 1998/05/28 16:51:50 drochner Exp $ */ + +/* + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 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. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <machine/bus.h> + +#include <dev/isa/isavar.h> + +#include <dev/ic/mc6845reg.h> +#include <dev/ic/pcdisplayvar.h> +#include <dev/isa/pcdisplayvar.h> + +#include <dev/ic/pcdisplay.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsdisplayvar.h> + +struct pcdisplay_config { + struct pcdisplayscreen pcs; + struct pcdisplay_handle dc_ph; + int mono; +}; + +struct pcdisplay_softc { + struct device sc_dev; + struct pcdisplay_config *sc_dc; + int nscreens; +}; + +static int pcdisplayconsole, pcdisplay_console_attached; +static struct pcdisplay_config pcdisplay_console_dc; + +int pcdisplay_match __P((struct device *, struct cfdata *, void *)); +void pcdisplay_attach __P((struct device *, struct device *, void *)); + +static int pcdisplay_is_console __P((bus_space_tag_t)); +static int pcdisplay_probe_col __P((bus_space_tag_t, bus_space_tag_t)); +static int pcdisplay_probe_mono __P((bus_space_tag_t, bus_space_tag_t)); +static void pcdisplay_init __P((struct pcdisplay_config *, + bus_space_tag_t, bus_space_tag_t, + int)); +static int pcdisplay_alloc_attr __P((void *, int, int, int, long *)); + +struct cfattach pcdisplay_ca = { + sizeof(struct pcdisplay_softc), pcdisplay_match, pcdisplay_attach, +}; + +const struct wsdisplay_emulops pcdisplay_emulops = { + pcdisplay_cursor, + pcdisplay_putstr, + pcdisplay_copycols, + pcdisplay_erasecols, + pcdisplay_copyrows, + pcdisplay_eraserows, + pcdisplay_alloc_attr +}; + +const struct wsscreen_descr pcdisplay_scr = { + "80x25", 80, 25, + &pcdisplay_emulops, + 0, 0, /* no font support */ + WSSCREEN_REVERSE /* that's minimal... */ +}; + +const struct wsscreen_descr *_pcdisplay_scrlist[] = { + &pcdisplay_scr, +}; + +const struct wsscreen_list pcdisplay_screenlist = { + sizeof(_pcdisplay_scrlist) / sizeof(struct wsscreen_descr *), + _pcdisplay_scrlist +}; + +static int pcdisplay_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); +static int pcdisplay_mmap __P((void *, off_t, int)); +static int pcdisplay_alloc_screen __P((void *, const struct wsscreen_descr *, + void **, int *, int *, long *)); +static void pcdisplay_free_screen __P((void *, void *)); +static void pcdisplay_show_screen __P((void *, void *)); +static int pcdisplay_load_font __P((void *, void *, int, int, int, void *)); + +const struct wsdisplay_accessops pcdisplay_accessops = { + pcdisplay_ioctl, + pcdisplay_mmap, + pcdisplay_alloc_screen, + pcdisplay_free_screen, + pcdisplay_show_screen, + pcdisplay_load_font +}; + +static int +pcdisplay_probe_col(iot, memt) + bus_space_tag_t iot, memt; +{ + bus_space_handle_t memh, ioh_6845; + u_int16_t oldval, val; + + if (bus_space_map(memt, 0xb8000, 0x8000, 0, &memh)) + return (0); + oldval = bus_space_read_2(memt, memh, 0); + bus_space_write_2(memt, memh, 0, 0xa55a); + val = bus_space_read_2(memt, memh, 0); + bus_space_write_2(memt, memh, 0, oldval); + bus_space_unmap(memt, memh, 0x8000); + if (val != 0xa55a) + return (0); + + if (bus_space_map(iot, 0x3d0, 0x10, 0, &ioh_6845)) + return (0); + bus_space_unmap(iot, ioh_6845, 0x10); + + return (1); +} + +static int +pcdisplay_probe_mono(iot, memt) + bus_space_tag_t iot, memt; +{ + bus_space_handle_t memh, ioh_6845; + u_int16_t oldval, val; + + if (bus_space_map(memt, 0xb0000, 0x8000, 0, &memh)) + return (0); + oldval = bus_space_read_2(memt, memh, 0); + bus_space_write_2(memt, memh, 0, 0xa55a); + val = bus_space_read_2(memt, memh, 0); + bus_space_write_2(memt, memh, 0, oldval); + bus_space_unmap(memt, memh, 0x8000); + if (val != 0xa55a) + return (0); + + if (bus_space_map(iot, 0x3b0, 0x10, 0, &ioh_6845)) + return (0); + bus_space_unmap(iot, ioh_6845, 0x10); + + return (1); +} + +static void +pcdisplay_init(dc, iot, memt, mono) + struct pcdisplay_config *dc; + bus_space_tag_t iot, memt; + int mono; +{ + struct pcdisplay_handle *ph = &dc->dc_ph; + int cpos; + + ph->ph_iot = iot; + ph->ph_memt = memt; + dc->mono = mono; + + if (bus_space_map(memt, mono ? 0xb0000 : 0xb8000, 0x8000, + 0, &ph->ph_memh)) + panic("pcdisplay_init: cannot map memory"); + if (bus_space_map(iot, mono ? 0x3b0 : 0x3d0, 0x10, + 0, &ph->ph_ioh_6845)) + panic("pcdisplay_init: cannot map io"); + + /* + * initialize the only screen + */ + dc->pcs.hdl = ph; + dc->pcs.type = &pcdisplay_scr; + dc->pcs.active = 1; + dc->pcs.mem = NULL; + + cpos = pcdisplay_6845_read(ph, cursorh) << 8; + cpos |= pcdisplay_6845_read(ph, cursorl); + + /* make sure we have a valid cursor position */ + if (cpos < 0 || cpos >= pcdisplay_scr.nrows * pcdisplay_scr.ncols) + cpos = 0; + + dc->pcs.vc_crow = cpos / pcdisplay_scr.ncols; + dc->pcs.vc_ccol = cpos % pcdisplay_scr.ncols; + dc->pcs.cursoron = 1; +} + +int +pcdisplay_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct isa_attach_args *ia = aux; + int mono; + + /* If values are hardwired to something that they can't be, punt. */ + if ((ia->ia_iobase != IOBASEUNK && + ia->ia_iobase != 0x3d0 && + ia->ia_iobase != 0x3b0) || + /* ia->ia_iosize != 0 || XXX isa.c */ + (ia->ia_maddr != MADDRUNK && + ia->ia_maddr != 0xb8000 && + ia->ia_maddr != 0xb0000) || + (ia->ia_msize != 0 && ia->ia_msize != 0x8000) || + ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK) + return (0); + + if (pcdisplay_is_console(ia->ia_iot)) + mono = pcdisplay_console_dc.mono; + else if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 && + pcdisplay_probe_col(ia->ia_iot, ia->ia_memt)) + mono = 0; + else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 && + pcdisplay_probe_mono(ia->ia_iot, ia->ia_memt)) + mono = 1; + else + return (0); + + ia->ia_iobase = mono ? 0x3b0 : 0x3d0; + ia->ia_iosize = 0x10; + ia->ia_maddr = mono ? 0xb0000 : 0xb8000; + ia->ia_msize = 0x8000; + return (1); +} + +void +pcdisplay_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct isa_attach_args *ia = aux; + struct pcdisplay_softc *sc = (struct pcdisplay_softc *)self; + int console; + struct pcdisplay_config *dc; + struct wsemuldisplaydev_attach_args aa; + + printf("\n"); + + console = pcdisplay_is_console(ia->ia_iot); + + if (console) { + dc = &pcdisplay_console_dc; + sc->nscreens = 1; + pcdisplay_console_attached = 1; + } else { + dc = malloc(sizeof(struct pcdisplay_config), + M_DEVBUF, M_WAITOK); + if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 && + pcdisplay_probe_col(ia->ia_iot, ia->ia_memt)) + pcdisplay_init(dc, ia->ia_iot, ia->ia_memt, 0); + else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 && + pcdisplay_probe_mono(ia->ia_iot, ia->ia_memt)) + pcdisplay_init(dc, ia->ia_iot, ia->ia_memt, 1); + else + panic("pcdisplay_attach: display disappeared"); + } + sc->sc_dc = dc; + + aa.console = console; + aa.scrdata = &pcdisplay_screenlist; + aa.accessops = &pcdisplay_accessops; + aa.accesscookie = sc; + + config_found(self, &aa, wsemuldisplaydevprint); +} + + +int +pcdisplay_cnattach(iot, memt) + bus_space_tag_t iot, memt; +{ + int mono; + + if (pcdisplay_probe_col(iot, memt)) + mono = 0; + else if (pcdisplay_probe_mono(iot, memt)) + mono = 1; + else + return (ENXIO); + + pcdisplay_init(&pcdisplay_console_dc, iot, memt, mono); + + wsdisplay_cnattach(&pcdisplay_scr, &pcdisplay_console_dc, + pcdisplay_console_dc.pcs.vc_ccol, + pcdisplay_console_dc.pcs.vc_crow, + FG_LIGHTGREY | BG_BLACK); + + pcdisplayconsole = 1; + return (0); +} + +static int +pcdisplay_is_console(iot) + bus_space_tag_t iot; +{ + if (pcdisplayconsole && + !pcdisplay_console_attached && + iot == pcdisplay_console_dc.dc_ph.ph_iot) + return (1); + return (0); +} + +static int +pcdisplay_ioctl(v, cmd, data, flag, p) + void *v; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + /* + * XXX "do something!" + */ + return (-1); +} + +static int +pcdisplay_mmap(v, offset, prot) + void *v; + off_t offset; + int prot; +{ + return (-1); +} + +static int +pcdisplay_alloc_screen(v, type, cookiep, curxp, curyp, defattrp) + void *v; + const struct wsscreen_descr *type; + void **cookiep; + int *curxp, *curyp; + long *defattrp; +{ + struct pcdisplay_softc *sc = v; + + if (sc->nscreens > 0) + return (ENOMEM); + + *cookiep = sc->sc_dc; + *curxp = 0; + *curyp = 0; + *defattrp = FG_LIGHTGREY | BG_BLACK; + sc->nscreens++; + return (0); +} + +static void +pcdisplay_free_screen(v, cookie) + void *v; + void *cookie; +{ + struct pcdisplay_softc *sc = v; + + if (sc->sc_dc == &pcdisplay_console_dc) + panic("pcdisplay_free_screen: console"); + + sc->nscreens--; +} + +static void +pcdisplay_show_screen(v, cookie) + void *v; + void *cookie; +{ +#ifdef DIAGNOSTIC + struct pcdisplay_softc *sc = v; + + if (cookie != sc->sc_dc) + panic("pcdisplay_show_screen: bad screen"); +#endif +} + +static int +pcdisplay_load_font(v, cookie, first, num, stride, data) + void *v; + void *cookie; + int first, num, stride; + void *data; +{ + return (EINVAL); +} + +static int +pcdisplay_alloc_attr(id, fg, bg, flags, attrp) + void *id; + int fg, bg; + int flags; + long *attrp; +{ + if (flags & WSATTR_REVERSE) + *attrp = FG_BLACK | BG_LIGHTGREY; + else + *attrp = FG_LIGHTGREY | BG_BLACK; + return (0); +} diff --git a/sys/dev/isa/pcdisplayvar.h b/sys/dev/isa/pcdisplayvar.h new file mode 100644 index 00000000000..43fb7c48e36 --- /dev/null +++ b/sys/dev/isa/pcdisplayvar.h @@ -0,0 +1,35 @@ +/* $NetBSD: pcdisplayvar.h,v 1.1 1998/05/28 16:51:51 drochner Exp $ */ + +/* + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 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. + * + */ + +int pcdisplay_cnattach __P((bus_space_tag_t, bus_space_tag_t)); |
