Annotation of sys/dev/isa/pcdisplay.c, Revision 1.1.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