Annotation of sys/dev/isa/pcdisplay.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pcdisplay.c,v 1.9 2006/11/29 19:08:22 miod Exp $ */
! 2: /* $NetBSD: pcdisplay.c,v 1.9.4.1 2000/06/30 16:27:48 simonb Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1998
! 6: * Matthias Drochner. All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 19: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 20: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 21: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 22: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 23: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 24: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 25: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 26: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 27: *
! 28: */
! 29:
! 30: #include <sys/param.h>
! 31: #include <sys/systm.h>
! 32: #include <sys/kernel.h>
! 33: #include <sys/device.h>
! 34: #include <sys/malloc.h>
! 35: #include <machine/bus.h>
! 36:
! 37: #include <dev/isa/isavar.h>
! 38: #include <dev/isa/isareg.h>
! 39:
! 40: #include <dev/ic/mc6845reg.h>
! 41: #include <dev/ic/pcdisplayvar.h>
! 42: #include <dev/isa/pcdisplayvar.h>
! 43:
! 44: #include <dev/ic/pcdisplay.h>
! 45:
! 46: #include <dev/wscons/wsconsio.h>
! 47: #include <dev/wscons/wsdisplayvar.h>
! 48:
! 49: struct pcdisplay_config {
! 50: struct pcdisplayscreen pcs;
! 51: struct pcdisplay_handle dc_ph;
! 52: int mono;
! 53: };
! 54:
! 55: struct pcdisplay_softc {
! 56: struct device sc_dev;
! 57: struct pcdisplay_config *sc_dc;
! 58: int nscreens;
! 59: };
! 60:
! 61: static int pcdisplayconsole, pcdisplay_console_attached;
! 62: static struct pcdisplay_config pcdisplay_console_dc;
! 63:
! 64: int pcdisplay_match(struct device *, void *, void *);
! 65: void pcdisplay_attach(struct device *, struct device *, void *);
! 66:
! 67: static int pcdisplay_is_console(bus_space_tag_t);
! 68: static int pcdisplay_probe_col(bus_space_tag_t, bus_space_tag_t);
! 69: static int pcdisplay_probe_mono(bus_space_tag_t, bus_space_tag_t);
! 70: static void pcdisplay_init(struct pcdisplay_config *,
! 71: bus_space_tag_t, bus_space_tag_t,
! 72: int);
! 73: static int pcdisplay_alloc_attr(void *, int, int, int, long *);
! 74: static void pcdisplay_unpack_attr(void *, long, int *, int *, int *);
! 75:
! 76: struct cfattach pcdisplay_ca = {
! 77: sizeof(struct pcdisplay_softc), pcdisplay_match, pcdisplay_attach,
! 78: };
! 79:
! 80: const struct wsdisplay_emulops pcdisplay_emulops = {
! 81: pcdisplay_cursor,
! 82: pcdisplay_mapchar,
! 83: pcdisplay_putchar,
! 84: pcdisplay_copycols,
! 85: pcdisplay_erasecols,
! 86: pcdisplay_copyrows,
! 87: pcdisplay_eraserows,
! 88: pcdisplay_alloc_attr,
! 89: pcdisplay_unpack_attr
! 90: };
! 91:
! 92: const struct wsscreen_descr pcdisplay_scr = {
! 93: "80x25", 80, 25,
! 94: &pcdisplay_emulops,
! 95: 0, 0, /* no font support */
! 96: WSSCREEN_REVERSE /* that's minimal... */
! 97: };
! 98:
! 99: const struct wsscreen_descr *_pcdisplay_scrlist[] = {
! 100: &pcdisplay_scr,
! 101: };
! 102:
! 103: const struct wsscreen_list pcdisplay_screenlist = {
! 104: sizeof(_pcdisplay_scrlist) / sizeof(struct wsscreen_descr *),
! 105: _pcdisplay_scrlist
! 106: };
! 107:
! 108: static int pcdisplay_ioctl(void *, u_long, caddr_t, int, struct proc *);
! 109: static paddr_t pcdisplay_mmap(void *, off_t, int);
! 110: static int pcdisplay_alloc_screen(void *, const struct wsscreen_descr *,
! 111: void **, int *, int *, long *);
! 112: static void pcdisplay_free_screen(void *, void *);
! 113: static int pcdisplay_show_screen(void *, void *, int,
! 114: void (*) (void *, int, int), void *);
! 115:
! 116: const struct wsdisplay_accessops pcdisplay_accessops = {
! 117: pcdisplay_ioctl,
! 118: pcdisplay_mmap,
! 119: pcdisplay_alloc_screen,
! 120: pcdisplay_free_screen,
! 121: pcdisplay_show_screen,
! 122: 0 /* load_font */
! 123: };
! 124:
! 125: static int
! 126: pcdisplay_probe_col(iot, memt)
! 127: bus_space_tag_t iot, memt;
! 128: {
! 129: bus_space_handle_t memh, ioh_6845;
! 130: u_int16_t oldval, val;
! 131:
! 132: if (bus_space_map(memt, 0xb8000, 0x8000, 0, &memh))
! 133: return (0);
! 134: oldval = bus_space_read_2(memt, memh, 0);
! 135: bus_space_write_2(memt, memh, 0, 0xa55a);
! 136: val = bus_space_read_2(memt, memh, 0);
! 137: bus_space_write_2(memt, memh, 0, oldval);
! 138: bus_space_unmap(memt, memh, 0x8000);
! 139: if (val != 0xa55a)
! 140: return (0);
! 141:
! 142: if (bus_space_map(iot, 0x3d0, 0x10, 0, &ioh_6845))
! 143: return (0);
! 144: bus_space_unmap(iot, ioh_6845, 0x10);
! 145:
! 146: return (1);
! 147: }
! 148:
! 149: static int
! 150: pcdisplay_probe_mono(iot, memt)
! 151: bus_space_tag_t iot, memt;
! 152: {
! 153: bus_space_handle_t memh, ioh_6845;
! 154: u_int16_t oldval, val;
! 155:
! 156: if (bus_space_map(memt, 0xb0000, 0x8000, 0, &memh))
! 157: return (0);
! 158: oldval = bus_space_read_2(memt, memh, 0);
! 159: bus_space_write_2(memt, memh, 0, 0xa55a);
! 160: val = bus_space_read_2(memt, memh, 0);
! 161: bus_space_write_2(memt, memh, 0, oldval);
! 162: bus_space_unmap(memt, memh, 0x8000);
! 163: if (val != 0xa55a)
! 164: return (0);
! 165:
! 166: if (bus_space_map(iot, 0x3b0, 0x10, 0, &ioh_6845))
! 167: return (0);
! 168: bus_space_unmap(iot, ioh_6845, 0x10);
! 169:
! 170: return (1);
! 171: }
! 172:
! 173: static void
! 174: pcdisplay_init(dc, iot, memt, mono)
! 175: struct pcdisplay_config *dc;
! 176: bus_space_tag_t iot, memt;
! 177: int mono;
! 178: {
! 179: struct pcdisplay_handle *ph = &dc->dc_ph;
! 180: int cpos;
! 181:
! 182: ph->ph_iot = iot;
! 183: ph->ph_memt = memt;
! 184: dc->mono = mono;
! 185:
! 186: if (bus_space_map(memt, mono ? 0xb0000 : 0xb8000, 0x8000,
! 187: 0, &ph->ph_memh))
! 188: panic("pcdisplay_init: cannot map memory");
! 189: if (bus_space_map(iot, mono ? 0x3b0 : 0x3d0, 0x10,
! 190: 0, &ph->ph_ioh_6845))
! 191: panic("pcdisplay_init: cannot map io");
! 192:
! 193: /*
! 194: * initialize the only screen
! 195: */
! 196: dc->pcs.hdl = ph;
! 197: dc->pcs.type = &pcdisplay_scr;
! 198: dc->pcs.active = 1;
! 199: dc->pcs.mem = NULL;
! 200:
! 201: cpos = pcdisplay_6845_read(ph, cursorh) << 8;
! 202: cpos |= pcdisplay_6845_read(ph, cursorl);
! 203:
! 204: /* make sure we have a valid cursor position */
! 205: if (cpos < 0 || cpos >= pcdisplay_scr.nrows * pcdisplay_scr.ncols)
! 206: cpos = 0;
! 207:
! 208: dc->pcs.dispoffset = 0;
! 209: dc->pcs.visibleoffset = 0;
! 210:
! 211: dc->pcs.vc_crow = cpos / pcdisplay_scr.ncols;
! 212: dc->pcs.vc_ccol = cpos % pcdisplay_scr.ncols;
! 213: pcdisplay_cursor_init(&dc->pcs, 1);
! 214: }
! 215:
! 216: int
! 217: pcdisplay_match(parent, match, aux)
! 218: struct device *parent;
! 219: void *match;
! 220: void *aux;
! 221: {
! 222: struct isa_attach_args *ia = aux;
! 223: int mono;
! 224:
! 225: /* If values are hardwired to something that they can't be, punt. */
! 226: if ((ia->ia_iobase != IOBASEUNK &&
! 227: ia->ia_iobase != 0x3d0 &&
! 228: ia->ia_iobase != 0x3b0) ||
! 229: /* ia->ia_iosize != 0 || XXX isa.c */
! 230: (ia->ia_maddr != MADDRUNK &&
! 231: ia->ia_maddr != 0xb8000 &&
! 232: ia->ia_maddr != 0xb0000) ||
! 233: (ia->ia_msize != 0 && ia->ia_msize != 0x8000) ||
! 234: ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK)
! 235: return (0);
! 236:
! 237: if (pcdisplay_is_console(ia->ia_iot))
! 238: mono = pcdisplay_console_dc.mono;
! 239: else if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 &&
! 240: pcdisplay_probe_col(ia->ia_iot, ia->ia_memt))
! 241: mono = 0;
! 242: else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 &&
! 243: pcdisplay_probe_mono(ia->ia_iot, ia->ia_memt))
! 244: mono = 1;
! 245: else
! 246: return (0);
! 247:
! 248: ia->ia_iobase = mono ? 0x3b0 : 0x3d0;
! 249: ia->ia_iosize = 0x10;
! 250: ia->ia_maddr = mono ? 0xb0000 : 0xb8000;
! 251: ia->ia_msize = 0x8000;
! 252: return (1);
! 253: }
! 254:
! 255: void
! 256: pcdisplay_attach(parent, self, aux)
! 257: struct device *parent, *self;
! 258: void *aux;
! 259: {
! 260: struct isa_attach_args *ia = aux;
! 261: struct pcdisplay_softc *sc = (struct pcdisplay_softc *)self;
! 262: int console;
! 263: struct pcdisplay_config *dc;
! 264: struct wsemuldisplaydev_attach_args aa;
! 265:
! 266: printf("\n");
! 267:
! 268: console = pcdisplay_is_console(ia->ia_iot);
! 269:
! 270: if (console) {
! 271: dc = &pcdisplay_console_dc;
! 272: sc->nscreens = 1;
! 273: pcdisplay_console_attached = 1;
! 274: } else {
! 275: dc = malloc(sizeof(struct pcdisplay_config),
! 276: M_DEVBUF, M_WAITOK);
! 277: if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 &&
! 278: pcdisplay_probe_col(ia->ia_iot, ia->ia_memt))
! 279: pcdisplay_init(dc, ia->ia_iot, ia->ia_memt, 0);
! 280: else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 &&
! 281: pcdisplay_probe_mono(ia->ia_iot, ia->ia_memt))
! 282: pcdisplay_init(dc, ia->ia_iot, ia->ia_memt, 1);
! 283: else
! 284: panic("pcdisplay_attach: display disappeared");
! 285: }
! 286: sc->sc_dc = dc;
! 287:
! 288: aa.console = console;
! 289: aa.scrdata = &pcdisplay_screenlist;
! 290: aa.accessops = &pcdisplay_accessops;
! 291: aa.accesscookie = sc;
! 292: aa.defaultscreens = 0;
! 293:
! 294: config_found(self, &aa, wsemuldisplaydevprint);
! 295: }
! 296:
! 297:
! 298: int
! 299: pcdisplay_cnattach(iot, memt)
! 300: bus_space_tag_t iot, memt;
! 301: {
! 302: int mono;
! 303:
! 304: if (pcdisplay_probe_col(iot, memt))
! 305: mono = 0;
! 306: else if (pcdisplay_probe_mono(iot, memt))
! 307: mono = 1;
! 308: else
! 309: return (ENXIO);
! 310:
! 311: pcdisplay_init(&pcdisplay_console_dc, iot, memt, mono);
! 312:
! 313: wsdisplay_cnattach(&pcdisplay_scr, &pcdisplay_console_dc,
! 314: pcdisplay_console_dc.pcs.vc_ccol,
! 315: pcdisplay_console_dc.pcs.vc_crow,
! 316: FG_LIGHTGREY | BG_BLACK);
! 317:
! 318: pcdisplayconsole = 1;
! 319: return (0);
! 320: }
! 321:
! 322: static int
! 323: pcdisplay_is_console(iot)
! 324: bus_space_tag_t iot;
! 325: {
! 326: if (pcdisplayconsole &&
! 327: !pcdisplay_console_attached &&
! 328: iot == pcdisplay_console_dc.dc_ph.ph_iot)
! 329: return (1);
! 330: return (0);
! 331: }
! 332:
! 333: static int
! 334: pcdisplay_ioctl(v, cmd, data, flag, p)
! 335: void *v;
! 336: u_long cmd;
! 337: caddr_t data;
! 338: int flag;
! 339: struct proc *p;
! 340: {
! 341: /*
! 342: * XXX "do something!"
! 343: */
! 344: return (-1);
! 345: }
! 346:
! 347: static paddr_t
! 348: pcdisplay_mmap(v, offset, prot)
! 349: void *v;
! 350: off_t offset;
! 351: int prot;
! 352: {
! 353: return (-1);
! 354: }
! 355:
! 356: static int
! 357: pcdisplay_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
! 358: void *v;
! 359: const struct wsscreen_descr *type;
! 360: void **cookiep;
! 361: int *curxp, *curyp;
! 362: long *defattrp;
! 363: {
! 364: struct pcdisplay_softc *sc = v;
! 365:
! 366: if (sc->nscreens > 0)
! 367: return (ENOMEM);
! 368:
! 369: *cookiep = sc->sc_dc;
! 370: *curxp = 0;
! 371: *curyp = 0;
! 372: *defattrp = FG_LIGHTGREY | BG_BLACK;
! 373: sc->nscreens++;
! 374: return (0);
! 375: }
! 376:
! 377: static void
! 378: pcdisplay_free_screen(v, cookie)
! 379: void *v;
! 380: void *cookie;
! 381: {
! 382: struct pcdisplay_softc *sc = v;
! 383:
! 384: if (sc->sc_dc == &pcdisplay_console_dc)
! 385: panic("pcdisplay_free_screen: console");
! 386:
! 387: sc->nscreens--;
! 388: }
! 389:
! 390: static int
! 391: pcdisplay_show_screen(v, cookie, waitok, cb, cbarg)
! 392: void *v;
! 393: void *cookie;
! 394: int waitok;
! 395: void (*cb)(void *, int, int);
! 396: void *cbarg;
! 397: {
! 398: #ifdef DIAGNOSTIC
! 399: struct pcdisplay_softc *sc = v;
! 400:
! 401: if (cookie != sc->sc_dc)
! 402: panic("pcdisplay_show_screen: bad screen");
! 403: #endif
! 404: return (0);
! 405: }
! 406:
! 407: static int
! 408: pcdisplay_alloc_attr(id, fg, bg, flags, attrp)
! 409: void *id;
! 410: int fg, bg;
! 411: int flags;
! 412: long *attrp;
! 413: {
! 414: if (flags & WSATTR_REVERSE)
! 415: *attrp = FG_BLACK | BG_LIGHTGREY;
! 416: else
! 417: *attrp = FG_LIGHTGREY | BG_BLACK;
! 418: return (0);
! 419: }
! 420:
! 421: static void
! 422: pcdisplay_unpack_attr(id, attr, fg, bg, ul)
! 423: void *id;
! 424: long attr;
! 425: int *fg, *bg, *ul;
! 426: {
! 427: if (attr == (FG_BLACK | BG_LIGHTGREY)) {
! 428: *fg = WSCOL_BLACK;
! 429: *bg = WSCOL_WHITE;
! 430: } else {
! 431: *fg = WSCOL_WHITE;
! 432: *bg = WSCOL_BLACK;
! 433: }
! 434: if (ul != NULL)
! 435: *ul = 0;
! 436: }
! 437:
! 438: struct cfdriver pcdisplay_cd = {
! 439: NULL, "pcdisplay", DV_DULL
! 440: };
CVSweb