pccons.c revision 1.16 1 /* $NetBSD: pccons.c,v 1.16 2000/03/06 21:36:06 thorpej Exp $ */
2 /* $OpenBSD: pccons.c,v 1.22 1999/01/30 22:39:37 imp Exp $ */
3 /* NetBSD: pccons.c,v 1.89 1995/05/04 19:35:20 cgd Exp */
4 /* NetBSD: pms.c,v 1.21 1995/04/18 02:25:18 mycroft Exp */
5
6 /*-
7 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
8 * Copyright (c) 1990 The Regents of the University of California.
9 * All rights reserved.
10 *
11 * This code is derived from software contributed to Berkeley by
12 * William Jolitz and Don Ahn.
13 *
14 * Copyright (c) 1994 Charles M. Hannum.
15 * Copyright (c) 1992, 1993 Erik Forsberg.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 * must display the following acknowledgement:
27 * This product includes software developed by the University of
28 * California, Berkeley and its contributors.
29 * 4. Neither the name of the University nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 *
45 * @(#)pccons.c 5.11 (Berkeley) 5/21/91
46 */
47
48 /*
49 * code to work keyboard & display for PC-style console
50 */
51
52 #include "opt_ddb.h"
53
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/ioctl.h>
57 #include <sys/proc.h>
58 #include <sys/user.h>
59 #include <sys/select.h>
60 #include <sys/tty.h>
61 #include <sys/uio.h>
62 #include <sys/callout.h>
63 #include <sys/syslog.h>
64 #include <sys/device.h>
65 #include <sys/poll.h>
66 #include <sys/conf.h>
67 #include <sys/vnode.h>
68 #include <sys/fcntl.h>
69 #include <sys/kernel.h>
70 #include <sys/kcore.h>
71
72 #include <dev/cons.h>
73
74 #include <machine/cpu.h>
75 #include <machine/pio.h>
76 #include <machine/autoconf.h>
77 #include <machine/bus.h>
78 #include <machine/display.h>
79 #include <machine/pccons.h>
80 #include <arc/arc/arctype.h>
81 #include <arc/arc/arcbios.h>
82 #include <arc/pica/pica.h>
83 #include <arc/dti/desktech.h>
84
85 #include <dev/isa/isavar.h>
86 #include <machine/isa_machdep.h>
87 #include <machine/kbdreg.h>
88
89 #include <dev/cons.h>
90
91 #define XFREE86_BUG_COMPAT
92
93 #ifndef BEEP_FREQ
94 #define BEEP_FREQ 1600
95 #endif
96 #ifndef BEEP_TIME
97 #define BEEP_TIME (hz/5)
98 #endif
99
100 #define PCBURST 128
101
102 static u_short *Crtat; /* pointer to backing store */
103 static u_short *crtat; /* pointer to current char */
104 static u_char async, kernel, polling; /* Really, you don't want to know. */
105 static u_char lock_state = 0x00, /* all off */
106 old_lock_state = 0xff,
107 typematic_rate = 0xff, /* don't update until set by user */
108 old_typematic_rate = 0xff;
109 static u_short cursor_shape = 0xffff, /* don't update until set by user */
110 old_cursor_shape = 0xffff;
111 static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */
112 int pc_xmode = 0;
113
114 cdev_decl(pc);
115
116 /*
117 * Keyboard output queue.
118 */
119 int kb_oq_put = 0;
120 int kb_oq_get = 0;
121 u_char kb_oq[8];
122
123 #define PCUNIT(x) (minor(x))
124
125 static struct video_state {
126 int cx, cy; /* escape parameters */
127 int row, col; /* current cursor position */
128 int nrow, ncol, nchr; /* current screen geometry */
129 int offset; /* Saved cursor pos */
130 u_char state; /* parser state */
131 #define VSS_ESCAPE 1
132 #define VSS_EBRACE 2
133 #define VSS_EPARAM 3
134 char so; /* in standout mode? */
135 char color; /* color or mono display */
136 char at; /* normal attributes */
137 char so_at; /* standout attributes */
138 } vs;
139
140 struct pc_softc {
141 struct device sc_dev;
142 struct tty *sc_tty;
143 };
144
145 struct opms_softc { /* driver status information */
146 struct device sc_dev;
147
148 struct clist sc_q;
149 struct selinfo sc_rsel;
150 u_char sc_state; /* mouse driver state */
151 #define PMS_OPEN 0x01 /* device is open */
152 #define PMS_ASLP 0x02 /* waiting for mouse data */
153 u_char sc_status; /* mouse button status */
154 int sc_x, sc_y; /* accumulated motion in the X,Y axis */
155 };
156
157 int pcprobe __P((struct device *, struct cfdata *, void *));
158 void pcattach __P((struct device *, struct device *, void *));
159 int pcintr __P((void *));
160 void pc_xmode_on __P((void));
161 void pc_xmode_off __P((void));
162 static u_char kbc_get8042cmd __P((void));
163 static int kbc_put8042cmd __P((u_char));
164 int kbc_8042sysreset __P((void));
165 int kbd_cmd __P((u_char, u_char));
166 static __inline int kbd_wait_output __P((void));
167 static __inline int kbd_wait_input __P((void));
168 static __inline void kbd_flush_input __P((void));
169 void set_cursor_shape __P((void));
170 void get_cursor_shape __P((void));
171 void async_update __P((void));
172 void do_async_update __P((u_char));;
173
174 void pccnattach __P((void));
175 void pccnputc __P((dev_t, int c));
176 int pccngetc __P((dev_t));
177 void pccnpollc __P((dev_t, int));
178
179 extern struct cfdriver pc_cd;
180
181 struct cfattach pc_pica_ca = {
182 sizeof(struct pc_softc), pcprobe, pcattach
183 };
184
185 struct cfattach pc_isa_ca = {
186 sizeof(struct pc_softc), pcprobe, pcattach
187 };
188 int opmsprobe __P((struct device *, struct cfdata *, void *));
189 void opmsattach __P((struct device *, struct device *, void *));
190 int opmsintr __P((void *));
191
192 struct cfattach opms_ca = {
193 sizeof(struct opms_softc), opmsprobe, opmsattach
194 };
195
196 extern struct cfdriver opms_cd;
197
198 #define PMSUNIT(dev) (minor(dev))
199
200 #define CHR 2
201
202 static unsigned int addr_6845;
203 static unsigned int mono_base = 0x3b4;
204 static unsigned int mono_buf = 0xb0000;
205 static unsigned int cga_base = 0x3d4;
206 static unsigned int cga_buf = 0xb8000;
207 static unsigned int kbd_cmdp = 0x64;
208 static unsigned int kbd_datap = 0x60;
209
210 char *sget __P((void));
211 void sput __P((u_char *, int));
212
213 void pcstart __P((struct tty *));
214 int pcparam __P((struct tty *, struct termios *));
215 static __inline void wcopy __P((void *, void *, u_int));
216
217 extern void fillw __P((int, u_int16_t *, int));
218
219 #define KBD_DELAY \
220 DELAY(10);
221
222 /*
223 * bcopy variant that only moves word-aligned 16-bit entities,
224 * for stupid VGA cards. cnt is required to be an even vale.
225 */
226 static __inline void
227 wcopy(src, tgt, cnt)
228 void *src, *tgt;
229 u_int cnt;
230 {
231 u_int16_t *from = src;
232 u_int16_t *to = tgt;
233
234 cnt >>= 1;
235 if (to < from || to >= from + cnt)
236 while(cnt--)
237 *to++ = *from++;
238 else {
239 to += cnt;
240 from += cnt;
241 while(cnt--)
242 *--to = *--from;
243 }
244 }
245
246 static __inline int
247 kbd_wait_output()
248 {
249 u_int i;
250
251 for (i = 100000; i; i--)
252 if ((inb(kbd_cmdp) & KBS_IBF) == 0) {
253 KBD_DELAY;
254 return 1;
255 }
256 return 0;
257 }
258
259 static __inline int
260 kbd_wait_input()
261 {
262 u_int i;
263
264 for (i = 100000; i; i--)
265 if ((inb(kbd_cmdp) & KBS_DIB) != 0) {
266 KBD_DELAY;
267 return 1;
268 }
269 return 0;
270 }
271
272 static __inline void
273 kbd_flush_input()
274 {
275 u_char c;
276
277 while ((c = inb(kbd_cmdp)) & 0x03)
278 if ((c & KBS_DIB) == KBS_DIB) {
279 /* XXX - delay is needed to prevent some keyboards from
280 wedging when the system boots */
281 delay(6);
282 (void) inb(kbd_datap);
283 }
284 }
285
286
287
288 /*
289 * Pass system reset command to keyboard controller (8042).
290 */
291 int
292 kbc_8042sysreset()
293 {
294
295 if (!kbd_wait_output())
296 return 0;
297 outb(kbd_cmdp, 0xd1);
298 if (!kbd_wait_output())
299 return 0;
300 outb(kbd_datap, 0); /* ZAP */
301 return 1;
302 }
303
304 #if 1
305 /*
306 * Get the current command byte.
307 */
308 static u_char
309 kbc_get8042cmd()
310 {
311
312 if (!kbd_wait_output())
313 return -1;
314 outb(kbd_cmdp, K_RDCMDBYTE);
315 if (!kbd_wait_input())
316 return -1;
317 return inb(kbd_datap);
318 }
319 #endif
320
321 /*
322 * Pass command byte to keyboard controller (8042).
323 */
324 static int
325 kbc_put8042cmd(val)
326 u_char val;
327 {
328
329 if (!kbd_wait_output())
330 return 0;
331 outb(kbd_cmdp, K_LDCMDBYTE);
332 if (!kbd_wait_output())
333 return 0;
334 outb(kbd_datap, val);
335 return 1;
336 }
337
338 /*
339 * Pass command to keyboard itself
340 */
341 int
342 kbd_cmd(val, polling)
343 u_char val;
344 u_char polling;
345 {
346 u_int retries = 3;
347 register u_int i;
348
349 if(!polling) {
350 i = spltty();
351 if(kb_oq_get == kb_oq_put) {
352 outb(kbd_datap, val);
353 }
354 kb_oq[kb_oq_put] = val;
355 kb_oq_put = (kb_oq_put + 1) & 7;
356 splx(i);
357 return(1);
358 }
359 else do {
360 if (!kbd_wait_output())
361 return 0;
362 outb(kbd_datap, val);
363 for (i = 100000; i; i--) {
364 if (inb(kbd_cmdp) & KBS_DIB) {
365 register u_char c;
366
367 KBD_DELAY;
368 c = inb(kbd_datap);
369 if (c == KBR_ACK || c == KBR_ECHO) {
370 return 1;
371 }
372 if (c == KBR_RESEND) {
373 break;
374 }
375 #ifdef DIAGNOSTIC
376 printf("kbd_cmd: input char %x lost\n", c);
377 #endif
378 }
379 }
380 } while (--retries);
381 return 0;
382 }
383
384 void
385 set_cursor_shape()
386 {
387 register int iobase = addr_6845;
388
389 outb(iobase, 10);
390 outb(iobase+1, cursor_shape >> 8);
391 outb(iobase, 11);
392 outb(iobase+1, cursor_shape);
393 old_cursor_shape = cursor_shape;
394 }
395
396 void
397 get_cursor_shape()
398 {
399 register int iobase = addr_6845;
400
401 outb(iobase, 10);
402 cursor_shape = inb(iobase+1) << 8;
403 outb(iobase, 11);
404 cursor_shape |= inb(iobase+1);
405
406 /*
407 * real 6845's, as found on, MDA, Hercules or CGA cards, do
408 * not support reading the cursor shape registers. the 6845
409 * tri-states it's data bus. This is _normally_ read by the
410 * cpu as either 0x00 or 0xff.. in which case we just use
411 * a line cursor.
412 */
413 if (cursor_shape == 0x0000 || cursor_shape == 0xffff)
414 cursor_shape = 0x0b10;
415 else
416 cursor_shape &= 0x1f1f;
417 }
418
419 void
420 do_async_update(poll)
421 u_char poll;
422 {
423 int pos;
424 static int old_pos = -1;
425
426 async = 0;
427
428 if (lock_state != old_lock_state) {
429 old_lock_state = lock_state;
430 if (!kbd_cmd(KBC_MODEIND, poll) ||
431 !kbd_cmd(lock_state, poll)) {
432 printf("pc: timeout updating leds\n");
433 (void) kbd_cmd(KBC_ENABLE, poll);
434 }
435 }
436 if (typematic_rate != old_typematic_rate) {
437 old_typematic_rate = typematic_rate;
438 if (!kbd_cmd(KBC_TYPEMATIC, poll) ||
439 !kbd_cmd(typematic_rate, poll)) {
440 printf("pc: timeout updating typematic rate\n");
441 (void) kbd_cmd(KBC_ENABLE, poll);
442 }
443 }
444
445 if (pc_xmode > 0)
446 return;
447
448 pos = crtat - Crtat;
449 if (pos != old_pos) {
450 register int iobase = addr_6845;
451 outb(iobase, 14);
452 outb(iobase+1, pos >> 8);
453 outb(iobase, 15);
454 outb(iobase+1, pos);
455 old_pos = pos;
456 }
457 if (cursor_shape != old_cursor_shape)
458 set_cursor_shape();
459 }
460
461 void
462 async_update()
463 {
464
465 if (kernel || polling) {
466 if (async)
467 untimeout((void(*)(void *))do_async_update, NULL);
468 do_async_update(1);
469 } else {
470 if (async)
471 return;
472 async = 1;
473 timeout((void(*)(void *))do_async_update, NULL, 1);
474 }
475 }
476
477 /*
478 * these are both bad jokes
479 */
480 int
481 pcprobe(parent, match, aux)
482 struct device *parent;
483 struct cfdata *match;
484 void *aux;
485 {
486 struct confargs *ca = aux;
487 u_int i;
488
489 /* Make shure we're looking for this type of device */
490 if(!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pica")) {
491 if(!BUS_MATCHNAME(ca, "pc"))
492 return(0);
493 }
494
495 /* Enable interrupts and keyboard, etc. */
496 if (!kbc_put8042cmd(CMDBYTE)) {
497 printf("pcprobe: command error\n");
498 return 0;
499 }
500
501 #if 1
502 /* Flush any garbage. */
503 kbd_flush_input();
504 /* Reset the keyboard. */
505 if (!kbd_cmd(KBC_RESET, 1)) {
506 printf("pcprobe: reset error %d\n", 1);
507 goto lose;
508 }
509 for (i = 600000; i; i--)
510 if ((inb(kbd_cmdp) & KBS_DIB) != 0) {
511 KBD_DELAY;
512 break;
513 }
514 if (i == 0 || inb(kbd_datap) != KBR_RSTDONE) {
515 printf("pcprobe: reset error %d\n", 2);
516 goto lose;
517 }
518 /*
519 * Some keyboards seem to leave a second ack byte after the reset.
520 * This is kind of stupid, but we account for them anyway by just
521 * flushing the buffer.
522 */
523 kbd_flush_input();
524 /* Just to be sure. */
525 if (!kbd_cmd(KBC_ENABLE, 1)) {
526 printf("pcprobe: reset error %d\n", 3);
527 goto lose;
528 }
529
530 /*
531 * Some keyboard/8042 combinations do not seem to work if the keyboard
532 * is set to table 1; in fact, it would appear that some keyboards just
533 * ignore the command altogether. So by default, we use the AT scan
534 * codes and have the 8042 translate them. Unfortunately, this is
535 * known to not work on some PS/2 machines. We try desparately to deal
536 * with this by checking the (lack of a) translate bit in the 8042 and
537 * attempting to set the keyboard to XT mode. If this all fails, well,
538 * tough luck.
539 *
540 * XXX It would perhaps be a better choice to just use AT scan codes
541 * and not bother with this.
542 */
543 if (kbc_get8042cmd() & KC8_TRANS) {
544 /* The 8042 is translating for us; use AT codes. */
545 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) {
546 printf("pcprobe: reset error %d\n", 4);
547 goto lose;
548 }
549 } else {
550 /* Stupid 8042; set keyboard to XT codes. */
551 if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) {
552 printf("pcprobe: reset error %d\n", 5);
553 goto lose;
554 }
555 }
556
557 lose:
558 /*
559 * Technically, we should probably fail the probe. But we'll be nice
560 * and allow keyboard-less machines to boot with the console.
561 */
562 #endif
563
564 return 1;
565 }
566
567 void
568 pcattach(parent, self, aux)
569 struct device *parent, *self;
570 void *aux;
571 {
572 struct confargs *ca = aux;
573 struct isa_attach_args *ia = aux;
574 struct pc_softc *sc = (void *)self;
575
576 printf(": %s\n", vs.color ? "color" : "mono");
577 do_async_update(1);
578
579 switch(cputype) {
580 case ACER_PICA_61:
581 BUS_INTR_ESTABLISH(ca, pcintr, (void *)(long)sc);
582 break;
583 case DESKSTATION_RPC44: /* XXX ick */
584 case DESKSTATION_TYNE:
585 isa_intr_establish(ia->ia_ic, ia->ia_irq, 1,
586 2, pcintr, sc); /*XXX ick */
587 break;
588 }
589 }
590
591 int
592 pcopen(dev, flag, mode, p)
593 dev_t dev;
594 int flag, mode;
595 struct proc *p;
596 {
597 struct pc_softc *sc;
598 int unit = PCUNIT(dev);
599 struct tty *tp;
600
601 if (unit >= pc_cd.cd_ndevs)
602 return ENXIO;
603 sc = pc_cd.cd_devs[unit];
604 if (sc == 0)
605 return ENXIO;
606
607 if (!sc->sc_tty) {
608 tp = sc->sc_tty = ttymalloc();
609 }
610 else {
611 tp = sc->sc_tty;
612 }
613
614 tp->t_oproc = pcstart;
615 tp->t_param = pcparam;
616 tp->t_dev = dev;
617 if ((tp->t_state & TS_ISOPEN) == 0) {
618 ttychars(tp);
619 tp->t_iflag = TTYDEF_IFLAG;
620 tp->t_oflag = TTYDEF_OFLAG;
621 tp->t_cflag = TTYDEF_CFLAG;
622 tp->t_lflag = TTYDEF_LFLAG;
623 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
624 pcparam(tp, &tp->t_termios);
625 ttsetwater(tp);
626 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
627 return EBUSY;
628 tp->t_state |= TS_CARR_ON;
629
630 return ((*linesw[tp->t_line].l_open)(dev, tp));
631 }
632
633 int
634 pcclose(dev, flag, mode, p)
635 dev_t dev;
636 int flag, mode;
637 struct proc *p;
638 {
639 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
640 struct tty *tp = sc->sc_tty;
641
642 (*linesw[tp->t_line].l_close)(tp, flag);
643 ttyclose(tp);
644 #ifdef notyet /* XXX */
645 ttyfree(tp);
646 #endif
647 return(0);
648 }
649
650 int
651 pcread(dev, uio, flag)
652 dev_t dev;
653 struct uio *uio;
654 int flag;
655 {
656 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
657 struct tty *tp = sc->sc_tty;
658
659 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
660 }
661
662 int
663 pcwrite(dev, uio, flag)
664 dev_t dev;
665 struct uio *uio;
666 int flag;
667 {
668 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
669 struct tty *tp = sc->sc_tty;
670
671 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
672 }
673
674 struct tty *
675 pctty(dev)
676 dev_t dev;
677 {
678 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
679 struct tty *tp = sc->sc_tty;
680
681 return (tp);
682 }
683
684 /*
685 * Got a console receive interrupt -
686 * the console processor wants to give us a character.
687 * Catch the character, and see who it goes to.
688 */
689 int
690 pcintr(arg)
691 void *arg;
692 {
693 struct pc_softc *sc = arg;
694 register struct tty *tp = sc->sc_tty;
695 u_char *cp;
696
697 if ((inb(kbd_cmdp) & KBS_DIB) == 0)
698 return 0;
699 if (polling)
700 return 1;
701 do {
702 cp = sget();
703 if (!tp || (tp->t_state & TS_ISOPEN) == 0)
704 return 1;
705 if (cp)
706 do
707 (*linesw[tp->t_line].l_rint)(*cp++, tp);
708 while (*cp);
709 } while (inb(kbd_cmdp) & KBS_DIB);
710 return 1;
711 }
712
713 int
714 pcioctl(dev, cmd, data, flag, p)
715 dev_t dev;
716 u_long cmd;
717 caddr_t data;
718 int flag;
719 struct proc *p;
720 {
721 struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
722 struct tty *tp = sc->sc_tty;
723 int error;
724
725 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
726 if (error >= 0)
727 return error;
728 error = ttioctl(tp, cmd, data, flag, p);
729 if (error >= 0)
730 return error;
731
732 switch (cmd) {
733 case CONSOLE_X_MODE_ON:
734 pc_xmode_on();
735 return 0;
736 case CONSOLE_X_MODE_OFF:
737 pc_xmode_off();
738 return 0;
739 case CONSOLE_X_BELL:
740 /*
741 * If set, data is a pointer to a length 2 array of
742 * integers. data[0] is the pitch in Hz and data[1]
743 * is the duration in msec.
744 */
745 if (data)
746 sysbeep(((int*)data)[0],
747 (((int*)data)[1] * hz) / 1000);
748 else
749 sysbeep(BEEP_FREQ, BEEP_TIME);
750 return 0;
751 case CONSOLE_SET_TYPEMATIC_RATE: {
752 u_char rate;
753
754 if (!data)
755 return EINVAL;
756 rate = *((u_char *)data);
757 /*
758 * Check that it isn't too big (which would cause it to be
759 * confused with a command).
760 */
761 if (rate & 0x80)
762 return EINVAL;
763 typematic_rate = rate;
764 async_update();
765 return 0;
766 }
767 case CONSOLE_SET_KEYMAP: {
768 pccons_keymap_t *map = (pccons_keymap_t *) data;
769 int i;
770
771 if (!data)
772 return EINVAL;
773 for (i = 0; i < KB_NUM_KEYS; i++)
774 if (map[i].unshift[KB_CODE_SIZE-1] ||
775 map[i].shift[KB_CODE_SIZE-1] ||
776 map[i].ctl[KB_CODE_SIZE-1] ||
777 map[i].altgr[KB_CODE_SIZE-1] ||
778 map[i].shift_altgr[KB_CODE_SIZE-1])
779 return EINVAL;
780
781 bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
782 return 0;
783 }
784 case CONSOLE_GET_KEYMAP:
785 if (!data)
786 return EINVAL;
787 bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
788 return 0;
789
790 default:
791 return ENOTTY;
792 }
793
794 #ifdef DIAGNOSTIC
795 panic("pcioctl: impossible");
796 #endif
797 }
798
799 void
800 pcstart(tp)
801 struct tty *tp;
802 {
803 struct clist *cl;
804 int s, len;
805 u_char buf[PCBURST];
806
807 s = spltty();
808 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
809 goto out;
810 tp->t_state |= TS_BUSY;
811 splx(s);
812 /*
813 * We need to do this outside spl since it could be fairly
814 * expensive and we don't want our serial ports to overflow.
815 */
816 cl = &tp->t_outq;
817 len = q_to_b(cl, buf, PCBURST);
818 sput(buf, len);
819 s = spltty();
820 tp->t_state &= ~TS_BUSY;
821 if (cl->c_cc) {
822 tp->t_state |= TS_TIMEOUT;
823 timeout(ttrstrt, tp, 1);
824 }
825 if (cl->c_cc <= tp->t_lowat) {
826 if (tp->t_state & TS_ASLEEP) {
827 tp->t_state &= ~TS_ASLEEP;
828 wakeup(cl);
829 }
830 selwakeup(&tp->t_wsel);
831 }
832 out:
833 splx(s);
834 }
835
836 void
837 pcstop(tp, flag)
838 struct tty *tp;
839 int flag;
840 {
841 }
842
843 /* ARGSUSED */
844 void
845 pccnattach()
846 {
847 int maj;
848 static struct consdev pccons = {
849 NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL,
850 NODEV, CN_NORMAL
851 };
852
853 /*
854 * For now, don't screw with it.
855 */
856 /* crtat = 0; */
857 switch(cputype) {
858
859 case ACER_PICA_61:
860 mono_base += PICA_V_LOCAL_VIDEO_CTRL;
861 mono_buf += PICA_V_LOCAL_VIDEO;
862 cga_base += PICA_V_LOCAL_VIDEO_CTRL;
863 cga_buf += PICA_V_LOCAL_VIDEO;
864 kbd_cmdp = PICA_SYS_KBD + 0x61;
865 kbd_datap = PICA_SYS_KBD + 0x60;
866 break;
867
868 case DESKSTATION_TYNE:
869 mono_base += arc_bus_io.bus_base;
870 mono_buf += arc_bus_mem.bus_base;
871 cga_base += arc_bus_io.bus_base;
872 cga_buf += arc_bus_mem.bus_base;
873 kbd_cmdp = arc_bus_io.bus_base + 0x64;
874 kbd_datap = arc_bus_io.bus_base + 0x60;
875 outb(arc_bus_io.bus_base + 0x3ce, 6); /* Correct video mode */
876 outb(arc_bus_io.bus_base + 0x3cf,
877 inb(arc_bus_io.bus_base + 0x3cf) | 0xc);
878 kbc_put8042cmd(CMDBYTE); /* Want XT codes.. */
879 break;
880
881 case DESKSTATION_RPC44:
882 mono_base += arc_bus_io.bus_base;
883 mono_buf += arc_bus_mem.bus_base;
884 cga_base += arc_bus_io.bus_base;
885 cga_buf = arc_bus_mem.bus_base + 0xa0000;
886 kbd_cmdp = arc_bus_io.bus_base + 0x64;
887 kbd_datap = arc_bus_io.bus_base + 0x60;
888 kbc_put8042cmd(CMDBYTE); /* Want XT codes.. */
889 break;
890
891 case SNI_RM200:
892 mono_base += arc_bus_io.bus_base;
893 mono_buf += arc_bus_mem.bus_base;
894 cga_base += arc_bus_io.bus_base;
895 cga_buf += arc_bus_mem.bus_base;
896 kbd_cmdp = arc_bus_io.bus_base + 0x64;
897 kbd_datap = arc_bus_io.bus_base + 0x60;
898 break;
899 }
900
901 /* locate the major number */
902 for (maj = 0; maj < nchrdev; maj++)
903 if (cdevsw[maj].d_open == pcopen)
904 break;
905 pccons.cn_dev = makedev(maj, 0);
906
907 cn_tab = &pccons;
908 }
909
910 /* ARGSUSED */
911 void
912 pccnputc(dev, c)
913 dev_t dev;
914 int c;
915 {
916 u_char cc, oldkernel = kernel;
917
918 kernel = 1;
919 if (c == '\n') {
920 sput("\r\n", 2);
921 } else {
922 cc = c;
923 sput(&cc, 1);
924 }
925 kernel = oldkernel;
926 }
927
928 /* ARGSUSED */
929 int
930 pccngetc(dev)
931 dev_t dev;
932 {
933 register char *cp;
934
935 if (pc_xmode > 0)
936 return 0;
937
938 do {
939 /* wait for byte */
940 while ((inb(kbd_cmdp) & KBS_DIB) == 0);
941 /* see if it's worthwhile */
942 cp = sget();
943 } while (!cp);
944 if (*cp == '\r')
945 return '\n';
946 return *cp;
947 }
948
949 void
950 pccnpollc(dev, on)
951 dev_t dev;
952 int on;
953 {
954
955 polling = on;
956 if (!on) {
957 int unit;
958 struct pc_softc *sc;
959 int s;
960
961 /*
962 * If disabling polling on a device that's been configured,
963 * make sure there are no bytes left in the FIFO, holding up
964 * the interrupt line. Otherwise we won't get any further
965 * interrupts.
966 */
967 unit = PCUNIT(dev);
968 if (pc_cd.cd_ndevs > unit) {
969 sc = pc_cd.cd_devs[unit];
970 if (sc != 0) {
971 s = spltty();
972 pcintr(sc);
973 splx(s);
974 }
975 }
976 }
977 }
978
979 /*
980 * Set line parameters.
981 */
982 int
983 pcparam(tp, t)
984 struct tty *tp;
985 struct termios *t;
986 {
987
988 tp->t_ispeed = t->c_ispeed;
989 tp->t_ospeed = t->c_ospeed;
990 tp->t_cflag = t->c_cflag;
991 return 0;
992 }
993
994 #define wrtchar(c, at) do {\
995 char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
996 } while (0)
997
998 /* translate ANSI color codes to standard pc ones */
999 static char fgansitopc[] = {
1000 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
1001 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
1002 };
1003
1004 static char bgansitopc[] = {
1005 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
1006 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
1007 };
1008
1009 static u_char iso2ibm437[] =
1010 {
1011 0, 0, 0, 0, 0, 0, 0, 0,
1012 0, 0, 0, 0, 0, 0, 0, 0,
1013 0, 0, 0, 0, 0, 0, 0, 0,
1014 0, 0, 0, 0, 0, 0, 0, 0,
1015 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40,
1016 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0,
1017 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa,
1018 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8,
1019 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80,
1020 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
1021 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f,
1022 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1,
1023 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87,
1024 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
1025 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f,
1026 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0
1027 };
1028
1029 /*
1030 * `pc3' termcap emulation.
1031 */
1032 void
1033 sput(cp, n)
1034 u_char *cp;
1035 int n;
1036 {
1037 u_char c, scroll = 0;
1038
1039 if (pc_xmode > 0)
1040 return;
1041
1042 if (crtat == 0) {
1043 volatile u_short *cp;
1044 u_short was;
1045 unsigned cursorat;
1046
1047 cp = (volatile u_short *)cga_buf;
1048 was = *cp;
1049 *cp = (volatile u_short) 0xA55A;
1050 if (*cp != 0xA55A) {
1051 cp = (volatile u_short *)mono_buf;
1052 addr_6845 = mono_base;
1053 vs.color = 0;
1054 } else {
1055 *cp = was;
1056 addr_6845 = cga_base;
1057 vs.color = 1;
1058 }
1059
1060 #ifdef FAT_CURSOR
1061 cursor_shape = 0x0012;
1062 #else
1063 get_cursor_shape();
1064 #endif
1065
1066 bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
1067 vs.nchr = vs.ncol * vs.nrow;
1068 vs.col--;
1069 vs.row--;
1070 cursorat = vs.ncol * vs.row + vs.col;
1071 vs.at = FG_LIGHTGREY | BG_BLACK;
1072
1073 Crtat = (u_short *)cp;
1074 crtat = Crtat + cursorat;
1075
1076 if (vs.color == 0)
1077 vs.so_at = FG_BLACK | BG_LIGHTGREY;
1078 else
1079 vs.so_at = FG_YELLOW | BG_BLACK;
1080
1081 fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
1082 }
1083
1084 while (n--) {
1085 if (!(c = *cp++))
1086 continue;
1087
1088 switch (c) {
1089 case 0x1B:
1090 if (vs.state >= VSS_ESCAPE) {
1091 wrtchar(c, vs.so_at);
1092 vs.state = 0;
1093 goto maybe_scroll;
1094 } else
1095 vs.state = VSS_ESCAPE;
1096 break;
1097
1098 case 0x9B: /* CSI */
1099 vs.cx = vs.cy = 0;
1100 vs.state = VSS_EBRACE;
1101 break;
1102
1103 case '\t': {
1104 int inccol = 8 - (vs.col & 7);
1105 crtat += inccol;
1106 vs.col += inccol;
1107 }
1108 maybe_scroll:
1109 if (vs.col >= vs.ncol) {
1110 vs.col -= vs.ncol;
1111 scroll = 1;
1112 }
1113 break;
1114
1115 case '\b':
1116 if (crtat <= Crtat)
1117 break;
1118 --crtat;
1119 if (--vs.col < 0)
1120 vs.col += vs.ncol; /* non-destructive backspace */
1121 break;
1122
1123 case '\r':
1124 crtat -= vs.col;
1125 vs.col = 0;
1126 break;
1127
1128 case '\n':
1129 crtat += vs.ncol;
1130 scroll = 1;
1131 break;
1132
1133 default:
1134 switch (vs.state) {
1135 case 0:
1136 if (c == '\a')
1137 sysbeep(BEEP_FREQ, BEEP_TIME);
1138 else {
1139 /*
1140 * If we're outputting multiple printed
1141 * characters, just blast them to the
1142 * screen until we reach the end of the
1143 * buffer or a control character. This
1144 * saves time by short-circuiting the
1145 * switch.
1146 * If we reach the end of the line, we
1147 * break to do a scroll check.
1148 */
1149 for (;;) {
1150 if (c & 0x80)
1151 c = iso2ibm437[c&0x7f];
1152
1153 if (vs.so)
1154 wrtchar(c, vs.so_at);
1155 else
1156 wrtchar(c, vs.at);
1157 if (vs.col >= vs.ncol) {
1158 vs.col = 0;
1159 scroll = 1;
1160 break;
1161 }
1162 if (!n || (c = *cp) < ' ')
1163 break;
1164 n--, cp++;
1165 }
1166 }
1167 break;
1168 case VSS_ESCAPE:
1169 switch (c) {
1170 case '[': /* Start ESC [ sequence */
1171 vs.cx = vs.cy = 0;
1172 vs.state = VSS_EBRACE;
1173 break;
1174 case 'c': /* Create screen & home */
1175 fillw((vs.at << 8) | ' ',
1176 Crtat, vs.nchr);
1177 crtat = Crtat;
1178 vs.col = 0;
1179 vs.state = 0;
1180 break;
1181 case '7': /* save cursor pos */
1182 vs.offset = crtat - Crtat;
1183 vs.state = 0;
1184 break;
1185 case '8': /* restore cursor pos */
1186 crtat = Crtat + vs.offset;
1187 vs.row = vs.offset / vs.ncol;
1188 vs.col = vs.offset % vs.ncol;
1189 vs.state = 0;
1190 break;
1191 default: /* Invalid, clear state */
1192 wrtchar(c, vs.so_at);
1193 vs.state = 0;
1194 goto maybe_scroll;
1195 }
1196 break;
1197
1198 default: /* VSS_EBRACE or VSS_EPARAM */
1199 switch (c) {
1200 int pos;
1201 case 'm':
1202 if (!vs.cx)
1203 vs.so = 0;
1204 else
1205 vs.so = 1;
1206 vs.state = 0;
1207 break;
1208 case 'A': { /* back cx rows */
1209 int cx = vs.cx;
1210 if (cx <= 0)
1211 cx = 1;
1212 else
1213 cx %= vs.nrow;
1214 pos = crtat - Crtat;
1215 pos -= vs.ncol * cx;
1216 if (pos < 0)
1217 pos += vs.nchr;
1218 crtat = Crtat + pos;
1219 vs.state = 0;
1220 break;
1221 }
1222 case 'B': { /* down cx rows */
1223 int cx = vs.cx;
1224 if (cx <= 0)
1225 cx = 1;
1226 else
1227 cx %= vs.nrow;
1228 pos = crtat - Crtat;
1229 pos += vs.ncol * cx;
1230 if (pos >= vs.nchr)
1231 pos -= vs.nchr;
1232 crtat = Crtat + pos;
1233 vs.state = 0;
1234 break;
1235 }
1236 case 'C': { /* right cursor */
1237 int cx = vs.cx,
1238 col = vs.col;
1239 if (cx <= 0)
1240 cx = 1;
1241 else
1242 cx %= vs.ncol;
1243 pos = crtat - Crtat;
1244 pos += cx;
1245 col += cx;
1246 if (col >= vs.ncol) {
1247 pos -= vs.ncol;
1248 col -= vs.ncol;
1249 }
1250 vs.col = col;
1251 crtat = Crtat + pos;
1252 vs.state = 0;
1253 break;
1254 }
1255 case 'D': { /* left cursor */
1256 int cx = vs.cx,
1257 col = vs.col;
1258 if (cx <= 0)
1259 cx = 1;
1260 else
1261 cx %= vs.ncol;
1262 pos = crtat - Crtat;
1263 pos -= cx;
1264 col -= cx;
1265 if (col < 0) {
1266 pos += vs.ncol;
1267 col += vs.ncol;
1268 }
1269 vs.col = col;
1270 crtat = Crtat + pos;
1271 vs.state = 0;
1272 break;
1273 }
1274 case 'J': /* Clear ... */
1275 switch (vs.cx) {
1276 case 0:
1277 /* ... to end of display */
1278 fillw((vs.at << 8) | ' ',
1279 crtat,
1280 Crtat + vs.nchr - crtat);
1281 break;
1282 case 1:
1283 /* ... to next location */
1284 fillw((vs.at << 8) | ' ',
1285 Crtat,
1286 crtat - Crtat + 1);
1287 break;
1288 case 2:
1289 /* ... whole display */
1290 fillw((vs.at << 8) | ' ',
1291 Crtat,
1292 vs.nchr);
1293 break;
1294 }
1295 vs.state = 0;
1296 break;
1297 case 'K': /* Clear line ... */
1298 switch (vs.cx) {
1299 case 0:
1300 /* ... current to EOL */
1301 fillw((vs.at << 8) | ' ',
1302 crtat,
1303 vs.ncol - vs.col);
1304 break;
1305 case 1:
1306 /* ... beginning to next */
1307 fillw((vs.at << 8) | ' ',
1308 crtat - vs.col,
1309 vs.col + 1);
1310 break;
1311 case 2:
1312 /* ... entire line */
1313 fillw((vs.at << 8) | ' ',
1314 crtat - vs.col, vs.ncol);
1315 break;
1316 }
1317 vs.state = 0;
1318 break;
1319 case 'f': /* in system V consoles */
1320 case 'H': { /* Cursor move */
1321 int cx = vs.cx,
1322 cy = vs.cy;
1323 if (!cx || !cy) {
1324 crtat = Crtat;
1325 vs.col = 0;
1326 } else {
1327 if (cx > vs.nrow)
1328 cx = vs.nrow;
1329 if (cy > vs.ncol)
1330 cy = vs.ncol;
1331 crtat = Crtat +
1332 (cx - 1) * vs.ncol + cy - 1;
1333 vs.col = cy - 1;
1334 }
1335 vs.state = 0;
1336 break;
1337 }
1338 case 'M': { /* delete cx rows */
1339 u_short *crtAt = crtat - vs.col;
1340 int cx = vs.cx,
1341 row = (crtAt - Crtat) / vs.ncol,
1342 nrow = vs.nrow - row;
1343 if (cx <= 0)
1344 cx = 1;
1345 else if (cx > nrow)
1346 cx = nrow;
1347 if (cx < nrow)
1348 #ifdef PCCONS_FORCE_WORD
1349 wcopy(crtAt + vs.ncol * cx,
1350 crtAt, vs.ncol * (nrow -
1351 cx) * CHR);
1352 #else
1353 bcopy(crtAt + vs.ncol * cx,
1354 crtAt, vs.ncol * (nrow -
1355 cx) * CHR);
1356 #endif
1357 fillw((vs.at << 8) | ' ',
1358 crtAt + vs.ncol * (nrow - cx),
1359 vs.ncol * cx);
1360 vs.state = 0;
1361 break;
1362 }
1363 case 'S': { /* scroll up cx lines */
1364 int cx = vs.cx;
1365 if (cx <= 0)
1366 cx = 1;
1367 else if (cx > vs.nrow)
1368 cx = vs.nrow;
1369 if (cx < vs.nrow)
1370 #ifdef PCCONS_FORCE_WORD
1371 wcopy(Crtat + vs.ncol * cx,
1372 Crtat, vs.ncol * (vs.nrow -
1373 cx) * CHR);
1374 #else
1375 bcopy(Crtat + vs.ncol * cx,
1376 Crtat, vs.ncol * (vs.nrow -
1377 cx) * CHR);
1378 #endif
1379 fillw((vs.at << 8) | ' ',
1380 Crtat + vs.ncol * (vs.nrow - cx),
1381 vs.ncol * cx);
1382 /* crtat -= vs.ncol * cx; XXX */
1383 vs.state = 0;
1384 break;
1385 }
1386 case 'L': { /* insert cx rows */
1387 u_short *crtAt = crtat - vs.col;
1388 int cx = vs.cx,
1389 row = (crtAt - Crtat) / vs.ncol,
1390 nrow = vs.nrow - row;
1391 if (cx <= 0)
1392 cx = 1;
1393 else if (cx > nrow)
1394 cx = nrow;
1395 if (cx < nrow)
1396 #ifdef PCCONS_FORCE_WORD
1397 wcopy(crtAt,
1398 crtAt + vs.ncol * cx,
1399 vs.ncol * (nrow - cx) *
1400 CHR);
1401 #else
1402 bcopy(crtAt,
1403 crtAt + vs.ncol * cx,
1404 vs.ncol * (nrow - cx) *
1405 CHR);
1406 #endif
1407 fillw((vs.at << 8) | ' ', crtAt,
1408 vs.ncol * cx);
1409 vs.state = 0;
1410 break;
1411 }
1412 case 'T': { /* scroll down cx lines */
1413 int cx = vs.cx;
1414 if (cx <= 0)
1415 cx = 1;
1416 else if (cx > vs.nrow)
1417 cx = vs.nrow;
1418 if (cx < vs.nrow)
1419 #ifdef PCCONS_FORCE_WORD
1420 wcopy(Crtat,
1421 Crtat + vs.ncol * cx,
1422 vs.ncol * (vs.nrow - cx) *
1423 CHR);
1424 #else
1425 bcopy(Crtat,
1426 Crtat + vs.ncol * cx,
1427 vs.ncol * (vs.nrow - cx) *
1428 CHR);
1429 #endif
1430 fillw((vs.at << 8) | ' ', Crtat,
1431 vs.ncol * cx);
1432 /* crtat += vs.ncol * cx; XXX */
1433 vs.state = 0;
1434 break;
1435 }
1436 case ';': /* Switch params in cursor def */
1437 vs.state = VSS_EPARAM;
1438 break;
1439 case 'r':
1440 vs.so_at = (vs.cx & FG_MASK) |
1441 ((vs.cy << 4) & BG_MASK);
1442 vs.state = 0;
1443 break;
1444 case 's': /* save cursor pos */
1445 vs.offset = crtat - Crtat;
1446 vs.state = 0;
1447 break;
1448 case 'u': /* restore cursor pos */
1449 crtat = Crtat + vs.offset;
1450 vs.row = vs.offset / vs.ncol;
1451 vs.col = vs.offset % vs.ncol;
1452 vs.state = 0;
1453 break;
1454 case 'x': /* set attributes */
1455 switch (vs.cx) {
1456 case 0:
1457 vs.at = FG_LIGHTGREY | BG_BLACK;
1458 break;
1459 case 1:
1460 /* ansi background */
1461 if (!vs.color)
1462 break;
1463 vs.at &= FG_MASK;
1464 vs.at |= bgansitopc[vs.cy & 7];
1465 break;
1466 case 2:
1467 /* ansi foreground */
1468 if (!vs.color)
1469 break;
1470 vs.at &= BG_MASK;
1471 vs.at |= fgansitopc[vs.cy & 7];
1472 break;
1473 case 3:
1474 /* pc text attribute */
1475 if (vs.state >= VSS_EPARAM)
1476 vs.at = vs.cy;
1477 break;
1478 }
1479 vs.state = 0;
1480 break;
1481
1482 default: /* Only numbers valid here */
1483 if ((c >= '0') && (c <= '9')) {
1484 if (vs.state >= VSS_EPARAM) {
1485 vs.cy *= 10;
1486 vs.cy += c - '0';
1487 } else {
1488 vs.cx *= 10;
1489 vs.cx += c - '0';
1490 }
1491 } else
1492 vs.state = 0;
1493 break;
1494 }
1495 break;
1496 }
1497 }
1498 if (scroll) {
1499 scroll = 0;
1500 /* scroll check */
1501 if (crtat >= Crtat + vs.nchr) {
1502 if (!kernel) {
1503 int s = spltty();
1504 if (lock_state & KB_SCROLL)
1505 tsleep(&lock_state,
1506 PUSER, "pcputc", 0);
1507 splx(s);
1508 }
1509 #if PCCONS_FORCE_WORD
1510 wcopy(Crtat + vs.ncol, Crtat,
1511 (vs.nchr - vs.ncol) * CHR);
1512 #else
1513 bcopy(Crtat + vs.ncol, Crtat,
1514 (vs.nchr - vs.ncol) * CHR);
1515 #endif
1516 fillw((vs.at << 8) | ' ',
1517 Crtat + vs.nchr - vs.ncol,
1518 vs.ncol);
1519 crtat -= vs.ncol;
1520 }
1521 }
1522 }
1523 async_update();
1524 }
1525
1526 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
1527 left and right shift when reading the keyboard map */
1528 static pccons_keymap_t scan_codes[KB_NUM_KEYS] = {
1529 /* type unshift shift control altgr shift_altgr scancode */
1530 { KB_NONE, "", "", "", "", ""}, /* 0 unused */
1531 { KB_ASCII, "\033", "\033", "\033", "", ""}, /* 1 ESCape */
1532 { KB_ASCII, "1", "!", "!", "", ""}, /* 2 1 */
1533 { KB_ASCII, "2", "@", "\000", "", ""}, /* 3 2 */
1534 { KB_ASCII, "3", "#", "#", "", ""}, /* 4 3 */
1535 { KB_ASCII, "4", "$", "$", "", ""}, /* 5 4 */
1536 { KB_ASCII, "5", "%", "%", "", ""}, /* 6 5 */
1537 { KB_ASCII, "6", "^", "\036", "", ""}, /* 7 6 */
1538 { KB_ASCII, "7", "&", "&", "", ""}, /* 8 7 */
1539 { KB_ASCII, "8", "*", "\010", "", ""}, /* 9 8 */
1540 { KB_ASCII, "9", "(", "(", "", ""}, /* 10 9 */
1541 { KB_ASCII, "0", ")", ")", "", ""}, /* 11 0 */
1542 { KB_ASCII, "-", "_", "\037", "", ""}, /* 12 - */
1543 { KB_ASCII, "=", "+", "+", "", ""}, /* 13 = */
1544 { KB_ASCII, "\177", "\177", "\010", "", ""}, /* 14 backspace */
1545 { KB_ASCII, "\t", "\t", "\t", "", ""}, /* 15 tab */
1546 { KB_ASCII, "q", "Q", "\021", "", ""}, /* 16 q */
1547 { KB_ASCII, "w", "W", "\027", "", ""}, /* 17 w */
1548 { KB_ASCII, "e", "E", "\005", "", ""}, /* 18 e */
1549 { KB_ASCII, "r", "R", "\022", "", ""}, /* 19 r */
1550 { KB_ASCII, "t", "T", "\024", "", ""}, /* 20 t */
1551 { KB_ASCII, "y", "Y", "\031", "", ""}, /* 21 y */
1552 { KB_ASCII, "u", "U", "\025", "", ""}, /* 22 u */
1553 { KB_ASCII, "i", "I", "\011", "", ""}, /* 23 i */
1554 { KB_ASCII, "o", "O", "\017", "", ""}, /* 24 o */
1555 { KB_ASCII, "p", "P", "\020", "", ""}, /* 25 p */
1556 { KB_ASCII, "[", "{", "\033", "", ""}, /* 26 [ */
1557 { KB_ASCII, "]", "}", "\035", "", ""}, /* 27 ] */
1558 { KB_ASCII, "\r", "\r", "\n", "", ""}, /* 28 return */
1559 { KB_CTL, "", "", "", "", ""}, /* 29 control */
1560 { KB_ASCII, "a", "A", "\001", "", ""}, /* 30 a */
1561 { KB_ASCII, "s", "S", "\023", "", ""}, /* 31 s */
1562 { KB_ASCII, "d", "D", "\004", "", ""}, /* 32 d */
1563 { KB_ASCII, "f", "F", "\006", "", ""}, /* 33 f */
1564 { KB_ASCII, "g", "G", "\007", "", ""}, /* 34 g */
1565 { KB_ASCII, "h", "H", "\010", "", ""}, /* 35 h */
1566 { KB_ASCII, "j", "J", "\n", "", ""}, /* 36 j */
1567 { KB_ASCII, "k", "K", "\013", "", ""}, /* 37 k */
1568 { KB_ASCII, "l", "L", "\014", "", ""}, /* 38 l */
1569 { KB_ASCII, ";", ":", ";", "", ""}, /* 39 ; */
1570 { KB_ASCII, "'", "\"", "'", "", ""}, /* 40 ' */
1571 { KB_ASCII, "`", "~", "`", "", ""}, /* 41 ` */
1572 { KB_SHIFT, "\001", "", "", "", ""}, /* 42 shift */
1573 { KB_ASCII, "\\", "|", "\034", "", ""}, /* 43 \ */
1574 { KB_ASCII, "z", "Z", "\032", "", ""}, /* 44 z */
1575 { KB_ASCII, "x", "X", "\030", "", ""}, /* 45 x */
1576 { KB_ASCII, "c", "C", "\003", "", ""}, /* 46 c */
1577 { KB_ASCII, "v", "V", "\026", "", ""}, /* 47 v */
1578 { KB_ASCII, "b", "B", "\002", "", ""}, /* 48 b */
1579 { KB_ASCII, "n", "N", "\016", "", ""}, /* 49 n */
1580 { KB_ASCII, "m", "M", "\r", "", ""}, /* 50 m */
1581 { KB_ASCII, ",", "<", "<", "", ""}, /* 51 , */
1582 { KB_ASCII, ".", ">", ">", "", ""}, /* 52 . */
1583 { KB_ASCII, "/", "?", "\037", "", ""}, /* 53 / */
1584 { KB_SHIFT, "\002", "", "", "", ""}, /* 54 shift */
1585 { KB_KP, "*", "*", "*", "", ""}, /* 55 kp * */
1586 { KB_ALT, "", "", "", "", ""}, /* 56 alt */
1587 { KB_ASCII, " ", " ", "\000", "", ""}, /* 57 space */
1588 { KB_CAPS, "", "", "", "", ""}, /* 58 caps */
1589 { KB_FUNC, "\033[M", "\033[Y", "\033[k", "", ""}, /* 59 f1 */
1590 { KB_FUNC, "\033[N", "\033[Z", "\033[l", "", ""}, /* 60 f2 */
1591 { KB_FUNC, "\033[O", "\033[a", "\033[m", "", ""}, /* 61 f3 */
1592 { KB_FUNC, "\033[P", "\033[b", "\033[n", "", ""}, /* 62 f4 */
1593 { KB_FUNC, "\033[Q", "\033[c", "\033[o", "", ""}, /* 63 f5 */
1594 { KB_FUNC, "\033[R", "\033[d", "\033[p", "", ""}, /* 64 f6 */
1595 { KB_FUNC, "\033[S", "\033[e", "\033[q", "", ""}, /* 65 f7 */
1596 { KB_FUNC, "\033[T", "\033[f", "\033[r", "", ""}, /* 66 f8 */
1597 { KB_FUNC, "\033[U", "\033[g", "\033[s", "", ""}, /* 67 f9 */
1598 { KB_FUNC, "\033[V", "\033[h", "\033[t", "", ""}, /* 68 f10 */
1599 { KB_NUM, "", "", "", "", ""}, /* 69 num lock */
1600 { KB_SCROLL, "", "", "", "", ""}, /* 70 scroll lock */
1601 { KB_KP, "7", "\033[H", "7", "", ""}, /* 71 kp 7 */
1602 { KB_KP, "8", "\033[A", "8", "", ""}, /* 72 kp 8 */
1603 { KB_KP, "9", "\033[I", "9", "", ""}, /* 73 kp 9 */
1604 { KB_KP, "-", "-", "-", "", ""}, /* 74 kp - */
1605 { KB_KP, "4", "\033[D", "4", "", ""}, /* 75 kp 4 */
1606 { KB_KP, "5", "\033[E", "5", "", ""}, /* 76 kp 5 */
1607 { KB_KP, "6", "\033[C", "6", "", ""}, /* 77 kp 6 */
1608 { KB_KP, "+", "+", "+", "", ""}, /* 78 kp + */
1609 { KB_KP, "1", "\033[F", "1", "", ""}, /* 79 kp 1 */
1610 { KB_KP, "2", "\033[B", "2", "", ""}, /* 80 kp 2 */
1611 { KB_KP, "3", "\033[G", "3", "", ""}, /* 81 kp 3 */
1612 { KB_KP, "0", "\033[L", "0", "", ""}, /* 82 kp 0 */
1613 { KB_KP, ",", "\177", ",", "", ""}, /* 83 kp , */
1614 { KB_NONE, "", "", "", "", ""}, /* 84 0 */
1615 { KB_NONE, "", "", "", "", ""}, /* 85 0 */
1616 { KB_NONE, "", "", "", "", ""}, /* 86 0 */
1617 { KB_FUNC, "\033[W", "\033[i", "\033[u", "", ""}, /* 87 f11 */
1618 { KB_FUNC, "\033[X", "\033[j", "\033[v", "", ""}, /* 88 f12 */
1619 { KB_NONE, "", "", "", "", ""}, /* 89 0 */
1620 { KB_NONE, "", "", "", "", ""}, /* 90 0 */
1621 { KB_NONE, "", "", "", "", ""}, /* 91 0 */
1622 { KB_NONE, "", "", "", "", ""}, /* 92 0 */
1623 { KB_NONE, "", "", "", "", ""}, /* 93 0 */
1624 { KB_NONE, "", "", "", "", ""}, /* 94 0 */
1625 { KB_NONE, "", "", "", "", ""}, /* 95 0 */
1626 { KB_NONE, "", "", "", "", ""}, /* 96 0 */
1627 { KB_NONE, "", "", "", "", ""}, /* 97 0 */
1628 { KB_NONE, "", "", "", "", ""}, /* 98 0 */
1629 { KB_NONE, "", "", "", "", ""}, /* 99 0 */
1630 { KB_NONE, "", "", "", "", ""}, /* 100 */
1631 { KB_NONE, "", "", "", "", ""}, /* 101 */
1632 { KB_NONE, "", "", "", "", ""}, /* 102 */
1633 { KB_NONE, "", "", "", "", ""}, /* 103 */
1634 { KB_NONE, "", "", "", "", ""}, /* 104 */
1635 { KB_NONE, "", "", "", "", ""}, /* 105 */
1636 { KB_NONE, "", "", "", "", ""}, /* 106 */
1637 { KB_NONE, "", "", "", "", ""}, /* 107 */
1638 { KB_NONE, "", "", "", "", ""}, /* 108 */
1639 { KB_NONE, "", "", "", "", ""}, /* 109 */
1640 { KB_NONE, "", "", "", "", ""}, /* 110 */
1641 { KB_NONE, "", "", "", "", ""}, /* 111 */
1642 { KB_NONE, "", "", "", "", ""}, /* 112 */
1643 { KB_NONE, "", "", "", "", ""}, /* 113 */
1644 { KB_NONE, "", "", "", "", ""}, /* 114 */
1645 { KB_NONE, "", "", "", "", ""}, /* 115 */
1646 { KB_NONE, "", "", "", "", ""}, /* 116 */
1647 { KB_NONE, "", "", "", "", ""}, /* 117 */
1648 { KB_NONE, "", "", "", "", ""}, /* 118 */
1649 { KB_NONE, "", "", "", "", ""}, /* 119 */
1650 { KB_NONE, "", "", "", "", ""}, /* 120 */
1651 { KB_NONE, "", "", "", "", ""}, /* 121 */
1652 { KB_NONE, "", "", "", "", ""}, /* 122 */
1653 { KB_NONE, "", "", "", "", ""}, /* 123 */
1654 { KB_NONE, "", "", "", "", ""}, /* 124 */
1655 { KB_NONE, "", "", "", "", ""}, /* 125 */
1656 { KB_NONE, "", "", "", "", ""}, /* 126 */
1657 { KB_NONE, "", "", "", "", ""} /* 127 */
1658 };
1659
1660 /*
1661 * Get characters from the keyboard. If none are present, return NULL.
1662 */
1663 char *
1664 sget()
1665 {
1666 u_char dt;
1667 static u_char extended = 0, shift_state = 0;
1668 static u_char capchar[2];
1669
1670 top:
1671 KBD_DELAY;
1672 dt = inb(kbd_datap);
1673
1674 switch (dt) {
1675 case KBR_ACK: case KBR_ECHO:
1676 kb_oq_get = (kb_oq_get + 1) & 7;
1677 if(kb_oq_get != kb_oq_put) {
1678 outb(kbd_datap, kb_oq[kb_oq_get]);
1679 }
1680 goto loop;
1681 case KBR_RESEND:
1682 outb(kbd_datap, kb_oq[kb_oq_get]);
1683 goto loop;
1684 }
1685
1686 if (pc_xmode > 0) {
1687 #if defined(DDB) && defined(XSERVER_DDB)
1688 /* F12 enters the debugger while in X mode */
1689 if (dt == 88)
1690 Debugger();
1691 #endif
1692 capchar[0] = dt;
1693 capchar[1] = 0;
1694 /*
1695 * Check for locking keys.
1696 *
1697 * XXX Setting the LEDs this way is a bit bogus. What if the
1698 * keyboard has been remapped in X?
1699 */
1700 switch (scan_codes[dt & 0x7f].type) {
1701 case KB_NUM:
1702 if (dt & 0x80) {
1703 shift_state &= ~KB_NUM;
1704 break;
1705 }
1706 if (shift_state & KB_NUM)
1707 break;
1708 shift_state |= KB_NUM;
1709 lock_state ^= KB_NUM;
1710 async_update();
1711 break;
1712 case KB_CAPS:
1713 if (dt & 0x80) {
1714 shift_state &= ~KB_CAPS;
1715 break;
1716 }
1717 if (shift_state & KB_CAPS)
1718 break;
1719 shift_state |= KB_CAPS;
1720 lock_state ^= KB_CAPS;
1721 async_update();
1722 break;
1723 case KB_SCROLL:
1724 if (dt & 0x80) {
1725 shift_state &= ~KB_SCROLL;
1726 break;
1727 }
1728 if (shift_state & KB_SCROLL)
1729 break;
1730 shift_state |= KB_SCROLL;
1731 lock_state ^= KB_SCROLL;
1732 if ((lock_state & KB_SCROLL) == 0)
1733 wakeup((caddr_t)&lock_state);
1734 async_update();
1735 break;
1736 }
1737 return capchar;
1738 }
1739
1740 switch (dt) {
1741 case KBR_EXTENDED:
1742 extended = 1;
1743 goto loop;
1744 }
1745
1746 #ifdef DDB
1747 /*
1748 * Check for cntl-alt-esc.
1749 */
1750 if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
1751 /* XXX - check pccons_is_console */
1752 Debugger();
1753 dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */
1754 }
1755 #endif
1756
1757 /*
1758 * Check for make/break.
1759 */
1760 if (dt & 0x80) {
1761 /*
1762 * break
1763 */
1764 dt &= 0x7f;
1765 switch (scan_codes[dt].type) {
1766 case KB_NUM:
1767 shift_state &= ~KB_NUM;
1768 break;
1769 case KB_CAPS:
1770 shift_state &= ~KB_CAPS;
1771 break;
1772 case KB_SCROLL:
1773 shift_state &= ~KB_SCROLL;
1774 break;
1775 case KB_SHIFT:
1776 shift_state &= ~KB_SHIFT;
1777 break;
1778 case KB_ALT:
1779 if (extended)
1780 shift_state &= ~KB_ALTGR;
1781 else
1782 shift_state &= ~KB_ALT;
1783 break;
1784 case KB_CTL:
1785 shift_state &= ~KB_CTL;
1786 break;
1787 }
1788 } else {
1789 /*
1790 * make
1791 */
1792 switch (scan_codes[dt].type) {
1793 /*
1794 * locking keys
1795 */
1796 case KB_NUM:
1797 if (shift_state & KB_NUM)
1798 break;
1799 shift_state |= KB_NUM;
1800 lock_state ^= KB_NUM;
1801 async_update();
1802 break;
1803 case KB_CAPS:
1804 if (shift_state & KB_CAPS)
1805 break;
1806 shift_state |= KB_CAPS;
1807 lock_state ^= KB_CAPS;
1808 async_update();
1809 break;
1810 case KB_SCROLL:
1811 if (shift_state & KB_SCROLL)
1812 break;
1813 shift_state |= KB_SCROLL;
1814 lock_state ^= KB_SCROLL;
1815 if ((lock_state & KB_SCROLL) == 0)
1816 wakeup((caddr_t)&lock_state);
1817 async_update();
1818 break;
1819 /*
1820 * non-locking keys
1821 */
1822 case KB_SHIFT:
1823 shift_state |= KB_SHIFT;
1824 break;
1825 case KB_ALT:
1826 if (extended)
1827 shift_state |= KB_ALTGR;
1828 else
1829 shift_state |= KB_ALT;
1830 break;
1831 case KB_CTL:
1832 shift_state |= KB_CTL;
1833 break;
1834 case KB_ASCII:
1835 /* control has highest priority */
1836 if (shift_state & KB_CTL)
1837 capchar[0] = scan_codes[dt].ctl[0];
1838 else if (shift_state & KB_ALTGR) {
1839 if (shift_state & KB_SHIFT)
1840 capchar[0] = scan_codes[dt].shift_altgr[0];
1841 else
1842 capchar[0] = scan_codes[dt].altgr[0];
1843 }
1844 else {
1845 if (shift_state & KB_SHIFT)
1846 capchar[0] = scan_codes[dt].shift[0];
1847 else
1848 capchar[0] = scan_codes[dt].unshift[0];
1849 }
1850 if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
1851 capchar[0] <= 'z') {
1852 capchar[0] -= ('a' - 'A');
1853 }
1854 capchar[0] |= (shift_state & KB_ALT);
1855 extended = 0;
1856 return capchar;
1857 case KB_NONE:
1858 printf("keycode %d\n",dt);
1859 break;
1860 case KB_FUNC: {
1861 char *more_chars;
1862 if (shift_state & KB_SHIFT)
1863 more_chars = scan_codes[dt].shift;
1864 else if (shift_state & KB_CTL)
1865 more_chars = scan_codes[dt].ctl;
1866 else
1867 more_chars = scan_codes[dt].unshift;
1868 extended = 0;
1869 return more_chars;
1870 }
1871 case KB_KP: {
1872 char *more_chars;
1873 if (shift_state & (KB_SHIFT | KB_CTL) ||
1874 (lock_state & KB_NUM) == 0 || extended)
1875 more_chars = scan_codes[dt].shift;
1876 else
1877 more_chars = scan_codes[dt].unshift;
1878 extended = 0;
1879 return more_chars;
1880 }
1881 }
1882 }
1883
1884 extended = 0;
1885 loop:
1886 if ((inb(kbd_cmdp) & KBS_DIB) == 0)
1887 return 0;
1888 goto top;
1889 }
1890
1891 int
1892 pcmmap(dev, offset, nprot)
1893 dev_t dev;
1894 int offset;
1895 int nprot;
1896 {
1897
1898 switch(cputype) {
1899
1900 case ACER_PICA_61:
1901 if (offset >= 0xa0000 && offset < 0xc0000)
1902 return mips_btop(PICA_P_LOCAL_VIDEO + offset);
1903 if (offset >= 0x0000 && offset < 0x10000)
1904 return mips_btop(PICA_P_LOCAL_VIDEO_CTRL + offset);
1905 if (offset >= 0x40000000 && offset < 0x40800000)
1906 return mips_btop(PICA_P_LOCAL_VIDEO + offset - 0x40000000);
1907 return -1;
1908
1909 case DESKSTATION_RPC44:
1910 if (offset >= 0xa0000 && offset < 0xc0000)
1911 return mips_btop(RPC44_P_ISA_MEM + offset);
1912 if (offset >= 0x0000 && offset < 0x10000)
1913 return mips_btop(RPC44_P_ISA_IO + offset);
1914 if (offset >= 0x40000000 && offset < 0x40800000)
1915 return mips_btop(RPC44_P_ISA_MEM + offset - 0x40000000);
1916 return -1;
1917
1918 case DESKSTATION_TYNE:
1919 /* Addresses returned are a fake to be able to handle >32 bit
1920 * physical addresses used by the tyne. The real physical adr
1921 * processing is done in pmap.c. Until we are a real 64 bit
1922 * port this is how it will be done.
1923 */
1924 /* XXX - the above is not supported merged pmap, yet */
1925 if (offset >= 0xa0000 && offset < 0xc0000)
1926 return mips_btop(TYNE_V_ISA_MEM + offset);
1927 if (offset >= 0x0000 && offset < 0x10000)
1928 return mips_btop(TYNE_V_ISA_IO + offset);
1929 if (offset >= 0x40000000 && offset < 0x40800000)
1930 return mips_btop(TYNE_V_ISA_MEM + offset - 0x40000000);
1931 return -1;
1932 }
1933 return -1;
1934 }
1935
1936 void
1937 pc_xmode_on()
1938 {
1939 if (pc_xmode)
1940 return;
1941 pc_xmode = 1;
1942
1943 #ifdef XFREE86_BUG_COMPAT
1944 /* If still unchanged, get current shape. */
1945 if (cursor_shape == 0xffff)
1946 get_cursor_shape();
1947 #endif
1948 }
1949
1950 void
1951 pc_xmode_off()
1952 {
1953 if (pc_xmode == 0)
1954 return;
1955 pc_xmode = 0;
1956
1957 #ifdef XFREE86_BUG_COMPAT
1958 /* XXX It would be hard to justify why the X server doesn't do this. */
1959 set_cursor_shape();
1960 #endif
1961 async_update();
1962 }
1963
1964 #include <machine/mouse.h>
1965
1966 /* status bits */
1967 #define PMS_OBUF_FULL 0x01
1968 #define PMS_IBUF_FULL 0x02
1969
1970 /* controller commands */
1971 #define PMS_INT_ENABLE 0x47 /* enable controller interrupts */
1972 #define PMS_INT_DISABLE 0x65 /* disable controller interrupts */
1973 #define PMS_AUX_ENABLE 0xa7 /* enable auxiliary port */
1974 #define PMS_AUX_DISABLE 0xa8 /* disable auxiliary port */
1975 #define PMS_MAGIC_1 0xa9 /* XXX */
1976
1977 #define PMS_8042_CMD 0x65
1978
1979 /* mouse commands */
1980 #define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
1981 #define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
1982 #define PMS_SET_RES 0xe8 /* set resolution */
1983 #define PMS_GET_SCALE 0xe9 /* get scaling factor */
1984 #define PMS_SET_STREAM 0xea /* set streaming mode */
1985 #define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
1986 #define PMS_DEV_ENABLE 0xf4 /* mouse on */
1987 #define PMS_DEV_DISABLE 0xf5 /* mouse off */
1988 #define PMS_RESET 0xff /* reset */
1989
1990 #define PMS_CHUNK 128 /* chunk size for read */
1991 #define PMS_BSIZE 1020 /* buffer size */
1992
1993 #define FLUSHQ(q) { if((q)->c_cc) ndflush(q, (q)->c_cc); }
1994
1995 int opmsopen __P((dev_t, int));
1996 int opmsclose __P((dev_t, int));
1997 int opmsread __P((dev_t, struct uio *, int));
1998 int opmsioctl __P((dev_t, u_long, caddr_t, int));
1999 int opmsselect __P((dev_t, int, struct proc *));
2000 int opmspoll __P((dev_t, int, struct proc *));
2001 static __inline void pms_dev_cmd __P((u_char));
2002 static __inline void pms_aux_cmd __P((u_char));
2003 static __inline void pms_pit_cmd __P((u_char));
2004
2005 static __inline void
2006 pms_dev_cmd(value)
2007 u_char value;
2008 {
2009 kbd_flush_input();
2010 outb(kbd_cmdp, 0xd4);
2011 kbd_flush_input();
2012 outb(kbd_datap, value);
2013 }
2014
2015 static __inline void
2016 pms_aux_cmd(value)
2017 u_char value;
2018 {
2019 kbd_flush_input();
2020 outb(kbd_cmdp, value);
2021 }
2022
2023 static __inline void
2024 pms_pit_cmd(value)
2025 u_char value;
2026 {
2027 kbd_flush_input();
2028 outb(kbd_cmdp, 0x60);
2029 kbd_flush_input();
2030 outb(kbd_datap, value);
2031 }
2032
2033 int
2034 opmsprobe(parent, match, aux)
2035 struct device *parent;
2036 struct cfdata *match;
2037 void *aux;
2038 {
2039 struct confargs *ca = aux;
2040 u_char x;
2041
2042 /* Make shure we're looking for this type of device */
2043 if(!BUS_MATCHNAME(ca, "pms"))
2044 return(0);
2045
2046 pms_dev_cmd(KBC_RESET);
2047 pms_aux_cmd(PMS_MAGIC_1);
2048 delay(10000);
2049 x = inb(kbd_datap);
2050 pms_pit_cmd(PMS_INT_DISABLE);
2051 if (x & 0x04)
2052 return 0;
2053
2054 return 1;
2055 }
2056
2057 void
2058 opmsattach(parent, self, aux)
2059 struct device *parent, *self;
2060 void *aux;
2061 {
2062 struct opms_softc *sc = (void *)self;
2063 struct confargs *ca = aux;
2064
2065 printf("\n");
2066
2067 /* Other initialization was done by opmsprobe. */
2068 sc->sc_state = 0;
2069
2070 BUS_INTR_ESTABLISH(ca, opmsintr, (void *)(long)sc);
2071 }
2072
2073 int
2074 opmsopen(dev, flag)
2075 dev_t dev;
2076 int flag;
2077 {
2078 int unit = PMSUNIT(dev);
2079 struct opms_softc *sc;
2080
2081 if (unit >= opms_cd.cd_ndevs)
2082 return ENXIO;
2083 sc = opms_cd.cd_devs[unit];
2084 if (!sc)
2085 return ENXIO;
2086
2087 if (sc->sc_state & PMS_OPEN)
2088 return EBUSY;
2089
2090 if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
2091 return ENOMEM;
2092
2093 sc->sc_state |= PMS_OPEN;
2094 sc->sc_status = 0;
2095 sc->sc_x = sc->sc_y = 0;
2096
2097 /* Enable interrupts. */
2098 pms_dev_cmd(PMS_DEV_ENABLE);
2099 pms_aux_cmd(PMS_AUX_ENABLE);
2100 pms_dev_cmd(PMS_SET_RES);
2101 pms_dev_cmd(3); /* 8 counts/mm */
2102 pms_dev_cmd(PMS_SET_SCALE21);
2103 #if 0
2104 pms_dev_cmd(PMS_SET_SAMPLE);
2105 pms_dev_cmd(100); /* 100 samples/sec */
2106 pms_dev_cmd(PMS_SET_STREAM);
2107 #endif
2108 pms_pit_cmd(PMS_INT_ENABLE);
2109
2110 return 0;
2111 }
2112
2113 int
2114 opmsclose(dev, flag)
2115 dev_t dev;
2116 int flag;
2117 {
2118 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2119
2120 /* Disable interrupts. */
2121 pms_dev_cmd(PMS_DEV_DISABLE);
2122 pms_pit_cmd(PMS_INT_DISABLE);
2123 pms_aux_cmd(PMS_AUX_DISABLE);
2124
2125 sc->sc_state &= ~PMS_OPEN;
2126
2127 clfree(&sc->sc_q);
2128
2129 return 0;
2130 }
2131
2132 int
2133 opmsread(dev, uio, flag)
2134 dev_t dev;
2135 struct uio *uio;
2136 int flag;
2137 {
2138 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2139 int s;
2140 int error = 0;
2141 size_t length;
2142 u_char buffer[PMS_CHUNK];
2143
2144 /* Block until mouse activity occured. */
2145
2146 s = spltty();
2147 while (sc->sc_q.c_cc == 0) {
2148 if (flag & IO_NDELAY) {
2149 splx(s);
2150 return EWOULDBLOCK;
2151 }
2152 sc->sc_state |= PMS_ASLP;
2153 error = tsleep((caddr_t)sc, PZERO | PCATCH, "pmsrea", 0);
2154 if (error) {
2155 sc->sc_state &= ~PMS_ASLP;
2156 splx(s);
2157 return error;
2158 }
2159 }
2160 splx(s);
2161
2162 /* Transfer as many chunks as possible. */
2163
2164 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
2165 length = min(sc->sc_q.c_cc, uio->uio_resid);
2166 if (length > sizeof(buffer))
2167 length = sizeof(buffer);
2168
2169 /* Remove a small chunk from the input queue. */
2170 (void) q_to_b(&sc->sc_q, buffer, length);
2171
2172 /* Copy the data to the user process. */
2173 error = uiomove(buffer, length, uio);
2174 if (error)
2175 break;
2176 }
2177
2178 return error;
2179 }
2180
2181 int
2182 opmsioctl(dev, cmd, addr, flag)
2183 dev_t dev;
2184 u_long cmd;
2185 caddr_t addr;
2186 int flag;
2187 {
2188 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2189 struct mouseinfo info;
2190 int s;
2191 int error;
2192
2193 switch (cmd) {
2194 case MOUSEIOCREAD:
2195 s = spltty();
2196
2197 info.status = sc->sc_status;
2198 if (sc->sc_x || sc->sc_y)
2199 info.status |= MOVEMENT;
2200
2201 if (sc->sc_x > 127)
2202 info.xmotion = 127;
2203 else if (sc->sc_x < -127)
2204 /* Bounding at -127 avoids a bug in XFree86. */
2205 info.xmotion = -127;
2206 else
2207 info.xmotion = sc->sc_x;
2208
2209 if (sc->sc_y > 127)
2210 info.ymotion = 127;
2211 else if (sc->sc_y < -127)
2212 info.ymotion = -127;
2213 else
2214 info.ymotion = sc->sc_y;
2215
2216 /* Reset historical information. */
2217 sc->sc_x = sc->sc_y = 0;
2218 sc->sc_status &= ~BUTCHNGMASK;
2219 ndflush(&sc->sc_q, sc->sc_q.c_cc);
2220
2221 splx(s);
2222 error = copyout(&info, addr, sizeof(struct mouseinfo));
2223 break;
2224 default:
2225 error = EINVAL;
2226 break;
2227 }
2228
2229 return error;
2230 }
2231
2232 /* Masks for the first byte of a packet */
2233 #define PS2LBUTMASK 0x01
2234 #define PS2RBUTMASK 0x02
2235 #define PS2MBUTMASK 0x04
2236
2237 int
2238 opmsintr(arg)
2239 void *arg;
2240 {
2241 struct opms_softc *sc = arg;
2242 static int state = 0;
2243 static u_char buttons;
2244 u_char changed;
2245 static char dx, dy;
2246 u_char buffer[5];
2247
2248 if ((sc->sc_state & PMS_OPEN) == 0) {
2249 /* Interrupts are not expected. Discard the byte. */
2250 kbd_flush_input();
2251 return 0;
2252 }
2253
2254 switch (state) {
2255
2256 case 0:
2257 buttons = inb(kbd_datap);
2258 if ((buttons & 0xc0) == 0)
2259 ++state;
2260 break;
2261
2262 case 1:
2263 dx = inb(kbd_datap);
2264 /* Bounding at -127 avoids a bug in XFree86. */
2265 dx = (dx == -128) ? -127 : dx;
2266 ++state;
2267 break;
2268
2269 case 2:
2270 dy = inb(kbd_datap);
2271 dy = (dy == -128) ? -127 : dy;
2272 state = 0;
2273
2274 buttons = ((buttons & PS2LBUTMASK) << 2) |
2275 ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
2276 changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
2277 sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
2278
2279 if (dx || dy || changed) {
2280 /* Update accumulated movements. */
2281 sc->sc_x += dx;
2282 sc->sc_y += dy;
2283
2284 /* Add this event to the queue. */
2285 buffer[0] = 0x80 | (buttons & BUTSTATMASK);
2286 if(dx < 0)
2287 buffer[0] |= 0x10;
2288 buffer[1] = dx & 0x7f;
2289 if(dy < 0)
2290 buffer[0] |= 0x20;
2291 buffer[2] = dy & 0x7f;
2292 buffer[3] = buffer[4] = 0;
2293 (void) b_to_q(buffer, sizeof buffer, &sc->sc_q);
2294
2295 if (sc->sc_state & PMS_ASLP) {
2296 sc->sc_state &= ~PMS_ASLP;
2297 wakeup((caddr_t)sc);
2298 }
2299 selwakeup(&sc->sc_rsel);
2300 }
2301
2302 break;
2303 }
2304 return -1;
2305 }
2306
2307 int
2308 opmspoll(dev, events, p)
2309 dev_t dev;
2310 int events;
2311 struct proc *p;
2312 {
2313 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2314 int revents = 0;
2315 int s = spltty();
2316
2317 if (events & (POLLIN | POLLRDNORM))
2318 if (sc->sc_q.c_cc > 0)
2319 revents |= events & (POLLIN | POLLRDNORM);
2320 else
2321 selrecord(p, &sc->sc_rsel);
2322
2323 splx(s);
2324 return (revents);
2325 }
2326