pccons.c revision 1.15 1 /* $NetBSD: pccons.c,v 1.15 2000/03/03 12:35:40 soda 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, NODEV, CN_NORMAL
850 };
851
852 /*
853 * For now, don't screw with it.
854 */
855 /* crtat = 0; */
856 switch(cputype) {
857
858 case ACER_PICA_61:
859 mono_base += PICA_V_LOCAL_VIDEO_CTRL;
860 mono_buf += PICA_V_LOCAL_VIDEO;
861 cga_base += PICA_V_LOCAL_VIDEO_CTRL;
862 cga_buf += PICA_V_LOCAL_VIDEO;
863 kbd_cmdp = PICA_SYS_KBD + 0x61;
864 kbd_datap = PICA_SYS_KBD + 0x60;
865 break;
866
867 case DESKSTATION_TYNE:
868 mono_base += arc_bus_io.bus_base;
869 mono_buf += arc_bus_mem.bus_base;
870 cga_base += arc_bus_io.bus_base;
871 cga_buf += arc_bus_mem.bus_base;
872 kbd_cmdp = arc_bus_io.bus_base + 0x64;
873 kbd_datap = arc_bus_io.bus_base + 0x60;
874 outb(arc_bus_io.bus_base + 0x3ce, 6); /* Correct video mode */
875 outb(arc_bus_io.bus_base + 0x3cf,
876 inb(arc_bus_io.bus_base + 0x3cf) | 0xc);
877 kbc_put8042cmd(CMDBYTE); /* Want XT codes.. */
878 break;
879
880 case DESKSTATION_RPC44:
881 mono_base += arc_bus_io.bus_base;
882 mono_buf += arc_bus_mem.bus_base;
883 cga_base += arc_bus_io.bus_base;
884 cga_buf = arc_bus_mem.bus_base + 0xa0000;
885 kbd_cmdp = arc_bus_io.bus_base + 0x64;
886 kbd_datap = arc_bus_io.bus_base + 0x60;
887 kbc_put8042cmd(CMDBYTE); /* Want XT codes.. */
888 break;
889
890 case SNI_RM200:
891 mono_base += arc_bus_io.bus_base;
892 mono_buf += arc_bus_mem.bus_base;
893 cga_base += arc_bus_io.bus_base;
894 cga_buf += arc_bus_mem.bus_base;
895 kbd_cmdp = arc_bus_io.bus_base + 0x64;
896 kbd_datap = arc_bus_io.bus_base + 0x60;
897 break;
898 }
899
900 /* locate the major number */
901 for (maj = 0; maj < nchrdev; maj++)
902 if (cdevsw[maj].d_open == pcopen)
903 break;
904 pccons.cn_dev = makedev(maj, 0);
905
906 cn_tab = &pccons;
907 }
908
909 /* ARGSUSED */
910 void
911 pccnputc(dev, c)
912 dev_t dev;
913 int c;
914 {
915 u_char cc, oldkernel = kernel;
916
917 kernel = 1;
918 if (c == '\n') {
919 sput("\r\n", 2);
920 } else {
921 cc = c;
922 sput(&cc, 1);
923 }
924 kernel = oldkernel;
925 }
926
927 /* ARGSUSED */
928 int
929 pccngetc(dev)
930 dev_t dev;
931 {
932 register char *cp;
933
934 if (pc_xmode > 0)
935 return 0;
936
937 do {
938 /* wait for byte */
939 while ((inb(kbd_cmdp) & KBS_DIB) == 0);
940 /* see if it's worthwhile */
941 cp = sget();
942 } while (!cp);
943 if (*cp == '\r')
944 return '\n';
945 return *cp;
946 }
947
948 void
949 pccnpollc(dev, on)
950 dev_t dev;
951 int on;
952 {
953
954 polling = on;
955 if (!on) {
956 int unit;
957 struct pc_softc *sc;
958 int s;
959
960 /*
961 * If disabling polling on a device that's been configured,
962 * make sure there are no bytes left in the FIFO, holding up
963 * the interrupt line. Otherwise we won't get any further
964 * interrupts.
965 */
966 unit = PCUNIT(dev);
967 if (pc_cd.cd_ndevs > unit) {
968 sc = pc_cd.cd_devs[unit];
969 if (sc != 0) {
970 s = spltty();
971 pcintr(sc);
972 splx(s);
973 }
974 }
975 }
976 }
977
978 /*
979 * Set line parameters.
980 */
981 int
982 pcparam(tp, t)
983 struct tty *tp;
984 struct termios *t;
985 {
986
987 tp->t_ispeed = t->c_ispeed;
988 tp->t_ospeed = t->c_ospeed;
989 tp->t_cflag = t->c_cflag;
990 return 0;
991 }
992
993 #define wrtchar(c, at) do {\
994 char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
995 } while (0)
996
997 /* translate ANSI color codes to standard pc ones */
998 static char fgansitopc[] = {
999 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
1000 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
1001 };
1002
1003 static char bgansitopc[] = {
1004 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
1005 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
1006 };
1007
1008 static u_char iso2ibm437[] =
1009 {
1010 0, 0, 0, 0, 0, 0, 0, 0,
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 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40,
1015 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0,
1016 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa,
1017 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8,
1018 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80,
1019 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
1020 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f,
1021 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1,
1022 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87,
1023 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
1024 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f,
1025 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0
1026 };
1027
1028 /*
1029 * `pc3' termcap emulation.
1030 */
1031 void
1032 sput(cp, n)
1033 u_char *cp;
1034 int n;
1035 {
1036 u_char c, scroll = 0;
1037
1038 if (pc_xmode > 0)
1039 return;
1040
1041 if (crtat == 0) {
1042 volatile u_short *cp;
1043 u_short was;
1044 unsigned cursorat;
1045
1046 cp = (volatile u_short *)cga_buf;
1047 was = *cp;
1048 *cp = (volatile u_short) 0xA55A;
1049 if (*cp != 0xA55A) {
1050 cp = (volatile u_short *)mono_buf;
1051 addr_6845 = mono_base;
1052 vs.color = 0;
1053 } else {
1054 *cp = was;
1055 addr_6845 = cga_base;
1056 vs.color = 1;
1057 }
1058
1059 #ifdef FAT_CURSOR
1060 cursor_shape = 0x0012;
1061 #else
1062 get_cursor_shape();
1063 #endif
1064
1065 bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
1066 vs.nchr = vs.ncol * vs.nrow;
1067 vs.col--;
1068 vs.row--;
1069 cursorat = vs.ncol * vs.row + vs.col;
1070 vs.at = FG_LIGHTGREY | BG_BLACK;
1071
1072 Crtat = (u_short *)cp;
1073 crtat = Crtat + cursorat;
1074
1075 if (vs.color == 0)
1076 vs.so_at = FG_BLACK | BG_LIGHTGREY;
1077 else
1078 vs.so_at = FG_YELLOW | BG_BLACK;
1079
1080 fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
1081 }
1082
1083 while (n--) {
1084 if (!(c = *cp++))
1085 continue;
1086
1087 switch (c) {
1088 case 0x1B:
1089 if (vs.state >= VSS_ESCAPE) {
1090 wrtchar(c, vs.so_at);
1091 vs.state = 0;
1092 goto maybe_scroll;
1093 } else
1094 vs.state = VSS_ESCAPE;
1095 break;
1096
1097 case 0x9B: /* CSI */
1098 vs.cx = vs.cy = 0;
1099 vs.state = VSS_EBRACE;
1100 break;
1101
1102 case '\t': {
1103 int inccol = 8 - (vs.col & 7);
1104 crtat += inccol;
1105 vs.col += inccol;
1106 }
1107 maybe_scroll:
1108 if (vs.col >= vs.ncol) {
1109 vs.col -= vs.ncol;
1110 scroll = 1;
1111 }
1112 break;
1113
1114 case '\b':
1115 if (crtat <= Crtat)
1116 break;
1117 --crtat;
1118 if (--vs.col < 0)
1119 vs.col += vs.ncol; /* non-destructive backspace */
1120 break;
1121
1122 case '\r':
1123 crtat -= vs.col;
1124 vs.col = 0;
1125 break;
1126
1127 case '\n':
1128 crtat += vs.ncol;
1129 scroll = 1;
1130 break;
1131
1132 default:
1133 switch (vs.state) {
1134 case 0:
1135 if (c == '\a')
1136 sysbeep(BEEP_FREQ, BEEP_TIME);
1137 else {
1138 /*
1139 * If we're outputting multiple printed
1140 * characters, just blast them to the
1141 * screen until we reach the end of the
1142 * buffer or a control character. This
1143 * saves time by short-circuiting the
1144 * switch.
1145 * If we reach the end of the line, we
1146 * break to do a scroll check.
1147 */
1148 for (;;) {
1149 if (c & 0x80)
1150 c = iso2ibm437[c&0x7f];
1151
1152 if (vs.so)
1153 wrtchar(c, vs.so_at);
1154 else
1155 wrtchar(c, vs.at);
1156 if (vs.col >= vs.ncol) {
1157 vs.col = 0;
1158 scroll = 1;
1159 break;
1160 }
1161 if (!n || (c = *cp) < ' ')
1162 break;
1163 n--, cp++;
1164 }
1165 }
1166 break;
1167 case VSS_ESCAPE:
1168 switch (c) {
1169 case '[': /* Start ESC [ sequence */
1170 vs.cx = vs.cy = 0;
1171 vs.state = VSS_EBRACE;
1172 break;
1173 case 'c': /* Create screen & home */
1174 fillw((vs.at << 8) | ' ',
1175 Crtat, vs.nchr);
1176 crtat = Crtat;
1177 vs.col = 0;
1178 vs.state = 0;
1179 break;
1180 case '7': /* save cursor pos */
1181 vs.offset = crtat - Crtat;
1182 vs.state = 0;
1183 break;
1184 case '8': /* restore cursor pos */
1185 crtat = Crtat + vs.offset;
1186 vs.row = vs.offset / vs.ncol;
1187 vs.col = vs.offset % vs.ncol;
1188 vs.state = 0;
1189 break;
1190 default: /* Invalid, clear state */
1191 wrtchar(c, vs.so_at);
1192 vs.state = 0;
1193 goto maybe_scroll;
1194 }
1195 break;
1196
1197 default: /* VSS_EBRACE or VSS_EPARAM */
1198 switch (c) {
1199 int pos;
1200 case 'm':
1201 if (!vs.cx)
1202 vs.so = 0;
1203 else
1204 vs.so = 1;
1205 vs.state = 0;
1206 break;
1207 case 'A': { /* back cx rows */
1208 int cx = vs.cx;
1209 if (cx <= 0)
1210 cx = 1;
1211 else
1212 cx %= vs.nrow;
1213 pos = crtat - Crtat;
1214 pos -= vs.ncol * cx;
1215 if (pos < 0)
1216 pos += vs.nchr;
1217 crtat = Crtat + pos;
1218 vs.state = 0;
1219 break;
1220 }
1221 case 'B': { /* down cx rows */
1222 int cx = vs.cx;
1223 if (cx <= 0)
1224 cx = 1;
1225 else
1226 cx %= vs.nrow;
1227 pos = crtat - Crtat;
1228 pos += vs.ncol * cx;
1229 if (pos >= vs.nchr)
1230 pos -= vs.nchr;
1231 crtat = Crtat + pos;
1232 vs.state = 0;
1233 break;
1234 }
1235 case 'C': { /* right cursor */
1236 int cx = vs.cx,
1237 col = vs.col;
1238 if (cx <= 0)
1239 cx = 1;
1240 else
1241 cx %= vs.ncol;
1242 pos = crtat - Crtat;
1243 pos += cx;
1244 col += cx;
1245 if (col >= vs.ncol) {
1246 pos -= vs.ncol;
1247 col -= vs.ncol;
1248 }
1249 vs.col = col;
1250 crtat = Crtat + pos;
1251 vs.state = 0;
1252 break;
1253 }
1254 case 'D': { /* left cursor */
1255 int cx = vs.cx,
1256 col = vs.col;
1257 if (cx <= 0)
1258 cx = 1;
1259 else
1260 cx %= vs.ncol;
1261 pos = crtat - Crtat;
1262 pos -= cx;
1263 col -= cx;
1264 if (col < 0) {
1265 pos += vs.ncol;
1266 col += vs.ncol;
1267 }
1268 vs.col = col;
1269 crtat = Crtat + pos;
1270 vs.state = 0;
1271 break;
1272 }
1273 case 'J': /* Clear ... */
1274 switch (vs.cx) {
1275 case 0:
1276 /* ... to end of display */
1277 fillw((vs.at << 8) | ' ',
1278 crtat,
1279 Crtat + vs.nchr - crtat);
1280 break;
1281 case 1:
1282 /* ... to next location */
1283 fillw((vs.at << 8) | ' ',
1284 Crtat,
1285 crtat - Crtat + 1);
1286 break;
1287 case 2:
1288 /* ... whole display */
1289 fillw((vs.at << 8) | ' ',
1290 Crtat,
1291 vs.nchr);
1292 break;
1293 }
1294 vs.state = 0;
1295 break;
1296 case 'K': /* Clear line ... */
1297 switch (vs.cx) {
1298 case 0:
1299 /* ... current to EOL */
1300 fillw((vs.at << 8) | ' ',
1301 crtat,
1302 vs.ncol - vs.col);
1303 break;
1304 case 1:
1305 /* ... beginning to next */
1306 fillw((vs.at << 8) | ' ',
1307 crtat - vs.col,
1308 vs.col + 1);
1309 break;
1310 case 2:
1311 /* ... entire line */
1312 fillw((vs.at << 8) | ' ',
1313 crtat - vs.col, vs.ncol);
1314 break;
1315 }
1316 vs.state = 0;
1317 break;
1318 case 'f': /* in system V consoles */
1319 case 'H': { /* Cursor move */
1320 int cx = vs.cx,
1321 cy = vs.cy;
1322 if (!cx || !cy) {
1323 crtat = Crtat;
1324 vs.col = 0;
1325 } else {
1326 if (cx > vs.nrow)
1327 cx = vs.nrow;
1328 if (cy > vs.ncol)
1329 cy = vs.ncol;
1330 crtat = Crtat +
1331 (cx - 1) * vs.ncol + cy - 1;
1332 vs.col = cy - 1;
1333 }
1334 vs.state = 0;
1335 break;
1336 }
1337 case 'M': { /* delete cx rows */
1338 u_short *crtAt = crtat - vs.col;
1339 int cx = vs.cx,
1340 row = (crtAt - Crtat) / vs.ncol,
1341 nrow = vs.nrow - row;
1342 if (cx <= 0)
1343 cx = 1;
1344 else if (cx > nrow)
1345 cx = nrow;
1346 if (cx < nrow)
1347 #ifdef PCCONS_FORCE_WORD
1348 wcopy(crtAt + vs.ncol * cx,
1349 crtAt, vs.ncol * (nrow -
1350 cx) * CHR);
1351 #else
1352 bcopy(crtAt + vs.ncol * cx,
1353 crtAt, vs.ncol * (nrow -
1354 cx) * CHR);
1355 #endif
1356 fillw((vs.at << 8) | ' ',
1357 crtAt + vs.ncol * (nrow - cx),
1358 vs.ncol * cx);
1359 vs.state = 0;
1360 break;
1361 }
1362 case 'S': { /* scroll up cx lines */
1363 int cx = vs.cx;
1364 if (cx <= 0)
1365 cx = 1;
1366 else if (cx > vs.nrow)
1367 cx = vs.nrow;
1368 if (cx < vs.nrow)
1369 #ifdef PCCONS_FORCE_WORD
1370 wcopy(Crtat + vs.ncol * cx,
1371 Crtat, vs.ncol * (vs.nrow -
1372 cx) * CHR);
1373 #else
1374 bcopy(Crtat + vs.ncol * cx,
1375 Crtat, vs.ncol * (vs.nrow -
1376 cx) * CHR);
1377 #endif
1378 fillw((vs.at << 8) | ' ',
1379 Crtat + vs.ncol * (vs.nrow - cx),
1380 vs.ncol * cx);
1381 /* crtat -= vs.ncol * cx; XXX */
1382 vs.state = 0;
1383 break;
1384 }
1385 case 'L': { /* insert cx rows */
1386 u_short *crtAt = crtat - vs.col;
1387 int cx = vs.cx,
1388 row = (crtAt - Crtat) / vs.ncol,
1389 nrow = vs.nrow - row;
1390 if (cx <= 0)
1391 cx = 1;
1392 else if (cx > nrow)
1393 cx = nrow;
1394 if (cx < nrow)
1395 #ifdef PCCONS_FORCE_WORD
1396 wcopy(crtAt,
1397 crtAt + vs.ncol * cx,
1398 vs.ncol * (nrow - cx) *
1399 CHR);
1400 #else
1401 bcopy(crtAt,
1402 crtAt + vs.ncol * cx,
1403 vs.ncol * (nrow - cx) *
1404 CHR);
1405 #endif
1406 fillw((vs.at << 8) | ' ', crtAt,
1407 vs.ncol * cx);
1408 vs.state = 0;
1409 break;
1410 }
1411 case 'T': { /* scroll down cx lines */
1412 int cx = vs.cx;
1413 if (cx <= 0)
1414 cx = 1;
1415 else if (cx > vs.nrow)
1416 cx = vs.nrow;
1417 if (cx < vs.nrow)
1418 #ifdef PCCONS_FORCE_WORD
1419 wcopy(Crtat,
1420 Crtat + vs.ncol * cx,
1421 vs.ncol * (vs.nrow - cx) *
1422 CHR);
1423 #else
1424 bcopy(Crtat,
1425 Crtat + vs.ncol * cx,
1426 vs.ncol * (vs.nrow - cx) *
1427 CHR);
1428 #endif
1429 fillw((vs.at << 8) | ' ', Crtat,
1430 vs.ncol * cx);
1431 /* crtat += vs.ncol * cx; XXX */
1432 vs.state = 0;
1433 break;
1434 }
1435 case ';': /* Switch params in cursor def */
1436 vs.state = VSS_EPARAM;
1437 break;
1438 case 'r':
1439 vs.so_at = (vs.cx & FG_MASK) |
1440 ((vs.cy << 4) & BG_MASK);
1441 vs.state = 0;
1442 break;
1443 case 's': /* save cursor pos */
1444 vs.offset = crtat - Crtat;
1445 vs.state = 0;
1446 break;
1447 case 'u': /* restore cursor pos */
1448 crtat = Crtat + vs.offset;
1449 vs.row = vs.offset / vs.ncol;
1450 vs.col = vs.offset % vs.ncol;
1451 vs.state = 0;
1452 break;
1453 case 'x': /* set attributes */
1454 switch (vs.cx) {
1455 case 0:
1456 vs.at = FG_LIGHTGREY | BG_BLACK;
1457 break;
1458 case 1:
1459 /* ansi background */
1460 if (!vs.color)
1461 break;
1462 vs.at &= FG_MASK;
1463 vs.at |= bgansitopc[vs.cy & 7];
1464 break;
1465 case 2:
1466 /* ansi foreground */
1467 if (!vs.color)
1468 break;
1469 vs.at &= BG_MASK;
1470 vs.at |= fgansitopc[vs.cy & 7];
1471 break;
1472 case 3:
1473 /* pc text attribute */
1474 if (vs.state >= VSS_EPARAM)
1475 vs.at = vs.cy;
1476 break;
1477 }
1478 vs.state = 0;
1479 break;
1480
1481 default: /* Only numbers valid here */
1482 if ((c >= '0') && (c <= '9')) {
1483 if (vs.state >= VSS_EPARAM) {
1484 vs.cy *= 10;
1485 vs.cy += c - '0';
1486 } else {
1487 vs.cx *= 10;
1488 vs.cx += c - '0';
1489 }
1490 } else
1491 vs.state = 0;
1492 break;
1493 }
1494 break;
1495 }
1496 }
1497 if (scroll) {
1498 scroll = 0;
1499 /* scroll check */
1500 if (crtat >= Crtat + vs.nchr) {
1501 if (!kernel) {
1502 int s = spltty();
1503 if (lock_state & KB_SCROLL)
1504 tsleep(&lock_state,
1505 PUSER, "pcputc", 0);
1506 splx(s);
1507 }
1508 #if PCCONS_FORCE_WORD
1509 wcopy(Crtat + vs.ncol, Crtat,
1510 (vs.nchr - vs.ncol) * CHR);
1511 #else
1512 bcopy(Crtat + vs.ncol, Crtat,
1513 (vs.nchr - vs.ncol) * CHR);
1514 #endif
1515 fillw((vs.at << 8) | ' ',
1516 Crtat + vs.nchr - vs.ncol,
1517 vs.ncol);
1518 crtat -= vs.ncol;
1519 }
1520 }
1521 }
1522 async_update();
1523 }
1524
1525 /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
1526 left and right shift when reading the keyboard map */
1527 static pccons_keymap_t scan_codes[KB_NUM_KEYS] = {
1528 /* type unshift shift control altgr shift_altgr scancode */
1529 { KB_NONE, "", "", "", "", ""}, /* 0 unused */
1530 { KB_ASCII, "\033", "\033", "\033", "", ""}, /* 1 ESCape */
1531 { KB_ASCII, "1", "!", "!", "", ""}, /* 2 1 */
1532 { KB_ASCII, "2", "@", "\000", "", ""}, /* 3 2 */
1533 { KB_ASCII, "3", "#", "#", "", ""}, /* 4 3 */
1534 { KB_ASCII, "4", "$", "$", "", ""}, /* 5 4 */
1535 { KB_ASCII, "5", "%", "%", "", ""}, /* 6 5 */
1536 { KB_ASCII, "6", "^", "\036", "", ""}, /* 7 6 */
1537 { KB_ASCII, "7", "&", "&", "", ""}, /* 8 7 */
1538 { KB_ASCII, "8", "*", "\010", "", ""}, /* 9 8 */
1539 { KB_ASCII, "9", "(", "(", "", ""}, /* 10 9 */
1540 { KB_ASCII, "0", ")", ")", "", ""}, /* 11 0 */
1541 { KB_ASCII, "-", "_", "\037", "", ""}, /* 12 - */
1542 { KB_ASCII, "=", "+", "+", "", ""}, /* 13 = */
1543 { KB_ASCII, "\177", "\177", "\010", "", ""}, /* 14 backspace */
1544 { KB_ASCII, "\t", "\t", "\t", "", ""}, /* 15 tab */
1545 { KB_ASCII, "q", "Q", "\021", "", ""}, /* 16 q */
1546 { KB_ASCII, "w", "W", "\027", "", ""}, /* 17 w */
1547 { KB_ASCII, "e", "E", "\005", "", ""}, /* 18 e */
1548 { KB_ASCII, "r", "R", "\022", "", ""}, /* 19 r */
1549 { KB_ASCII, "t", "T", "\024", "", ""}, /* 20 t */
1550 { KB_ASCII, "y", "Y", "\031", "", ""}, /* 21 y */
1551 { KB_ASCII, "u", "U", "\025", "", ""}, /* 22 u */
1552 { KB_ASCII, "i", "I", "\011", "", ""}, /* 23 i */
1553 { KB_ASCII, "o", "O", "\017", "", ""}, /* 24 o */
1554 { KB_ASCII, "p", "P", "\020", "", ""}, /* 25 p */
1555 { KB_ASCII, "[", "{", "\033", "", ""}, /* 26 [ */
1556 { KB_ASCII, "]", "}", "\035", "", ""}, /* 27 ] */
1557 { KB_ASCII, "\r", "\r", "\n", "", ""}, /* 28 return */
1558 { KB_CTL, "", "", "", "", ""}, /* 29 control */
1559 { KB_ASCII, "a", "A", "\001", "", ""}, /* 30 a */
1560 { KB_ASCII, "s", "S", "\023", "", ""}, /* 31 s */
1561 { KB_ASCII, "d", "D", "\004", "", ""}, /* 32 d */
1562 { KB_ASCII, "f", "F", "\006", "", ""}, /* 33 f */
1563 { KB_ASCII, "g", "G", "\007", "", ""}, /* 34 g */
1564 { KB_ASCII, "h", "H", "\010", "", ""}, /* 35 h */
1565 { KB_ASCII, "j", "J", "\n", "", ""}, /* 36 j */
1566 { KB_ASCII, "k", "K", "\013", "", ""}, /* 37 k */
1567 { KB_ASCII, "l", "L", "\014", "", ""}, /* 38 l */
1568 { KB_ASCII, ";", ":", ";", "", ""}, /* 39 ; */
1569 { KB_ASCII, "'", "\"", "'", "", ""}, /* 40 ' */
1570 { KB_ASCII, "`", "~", "`", "", ""}, /* 41 ` */
1571 { KB_SHIFT, "\001", "", "", "", ""}, /* 42 shift */
1572 { KB_ASCII, "\\", "|", "\034", "", ""}, /* 43 \ */
1573 { KB_ASCII, "z", "Z", "\032", "", ""}, /* 44 z */
1574 { KB_ASCII, "x", "X", "\030", "", ""}, /* 45 x */
1575 { KB_ASCII, "c", "C", "\003", "", ""}, /* 46 c */
1576 { KB_ASCII, "v", "V", "\026", "", ""}, /* 47 v */
1577 { KB_ASCII, "b", "B", "\002", "", ""}, /* 48 b */
1578 { KB_ASCII, "n", "N", "\016", "", ""}, /* 49 n */
1579 { KB_ASCII, "m", "M", "\r", "", ""}, /* 50 m */
1580 { KB_ASCII, ",", "<", "<", "", ""}, /* 51 , */
1581 { KB_ASCII, ".", ">", ">", "", ""}, /* 52 . */
1582 { KB_ASCII, "/", "?", "\037", "", ""}, /* 53 / */
1583 { KB_SHIFT, "\002", "", "", "", ""}, /* 54 shift */
1584 { KB_KP, "*", "*", "*", "", ""}, /* 55 kp * */
1585 { KB_ALT, "", "", "", "", ""}, /* 56 alt */
1586 { KB_ASCII, " ", " ", "\000", "", ""}, /* 57 space */
1587 { KB_CAPS, "", "", "", "", ""}, /* 58 caps */
1588 { KB_FUNC, "\033[M", "\033[Y", "\033[k", "", ""}, /* 59 f1 */
1589 { KB_FUNC, "\033[N", "\033[Z", "\033[l", "", ""}, /* 60 f2 */
1590 { KB_FUNC, "\033[O", "\033[a", "\033[m", "", ""}, /* 61 f3 */
1591 { KB_FUNC, "\033[P", "\033[b", "\033[n", "", ""}, /* 62 f4 */
1592 { KB_FUNC, "\033[Q", "\033[c", "\033[o", "", ""}, /* 63 f5 */
1593 { KB_FUNC, "\033[R", "\033[d", "\033[p", "", ""}, /* 64 f6 */
1594 { KB_FUNC, "\033[S", "\033[e", "\033[q", "", ""}, /* 65 f7 */
1595 { KB_FUNC, "\033[T", "\033[f", "\033[r", "", ""}, /* 66 f8 */
1596 { KB_FUNC, "\033[U", "\033[g", "\033[s", "", ""}, /* 67 f9 */
1597 { KB_FUNC, "\033[V", "\033[h", "\033[t", "", ""}, /* 68 f10 */
1598 { KB_NUM, "", "", "", "", ""}, /* 69 num lock */
1599 { KB_SCROLL, "", "", "", "", ""}, /* 70 scroll lock */
1600 { KB_KP, "7", "\033[H", "7", "", ""}, /* 71 kp 7 */
1601 { KB_KP, "8", "\033[A", "8", "", ""}, /* 72 kp 8 */
1602 { KB_KP, "9", "\033[I", "9", "", ""}, /* 73 kp 9 */
1603 { KB_KP, "-", "-", "-", "", ""}, /* 74 kp - */
1604 { KB_KP, "4", "\033[D", "4", "", ""}, /* 75 kp 4 */
1605 { KB_KP, "5", "\033[E", "5", "", ""}, /* 76 kp 5 */
1606 { KB_KP, "6", "\033[C", "6", "", ""}, /* 77 kp 6 */
1607 { KB_KP, "+", "+", "+", "", ""}, /* 78 kp + */
1608 { KB_KP, "1", "\033[F", "1", "", ""}, /* 79 kp 1 */
1609 { KB_KP, "2", "\033[B", "2", "", ""}, /* 80 kp 2 */
1610 { KB_KP, "3", "\033[G", "3", "", ""}, /* 81 kp 3 */
1611 { KB_KP, "0", "\033[L", "0", "", ""}, /* 82 kp 0 */
1612 { KB_KP, ",", "\177", ",", "", ""}, /* 83 kp , */
1613 { KB_NONE, "", "", "", "", ""}, /* 84 0 */
1614 { KB_NONE, "", "", "", "", ""}, /* 85 0 */
1615 { KB_NONE, "", "", "", "", ""}, /* 86 0 */
1616 { KB_FUNC, "\033[W", "\033[i", "\033[u", "", ""}, /* 87 f11 */
1617 { KB_FUNC, "\033[X", "\033[j", "\033[v", "", ""}, /* 88 f12 */
1618 { KB_NONE, "", "", "", "", ""}, /* 89 0 */
1619 { KB_NONE, "", "", "", "", ""}, /* 90 0 */
1620 { KB_NONE, "", "", "", "", ""}, /* 91 0 */
1621 { KB_NONE, "", "", "", "", ""}, /* 92 0 */
1622 { KB_NONE, "", "", "", "", ""}, /* 93 0 */
1623 { KB_NONE, "", "", "", "", ""}, /* 94 0 */
1624 { KB_NONE, "", "", "", "", ""}, /* 95 0 */
1625 { KB_NONE, "", "", "", "", ""}, /* 96 0 */
1626 { KB_NONE, "", "", "", "", ""}, /* 97 0 */
1627 { KB_NONE, "", "", "", "", ""}, /* 98 0 */
1628 { KB_NONE, "", "", "", "", ""}, /* 99 0 */
1629 { KB_NONE, "", "", "", "", ""}, /* 100 */
1630 { KB_NONE, "", "", "", "", ""}, /* 101 */
1631 { KB_NONE, "", "", "", "", ""}, /* 102 */
1632 { KB_NONE, "", "", "", "", ""}, /* 103 */
1633 { KB_NONE, "", "", "", "", ""}, /* 104 */
1634 { KB_NONE, "", "", "", "", ""}, /* 105 */
1635 { KB_NONE, "", "", "", "", ""}, /* 106 */
1636 { KB_NONE, "", "", "", "", ""}, /* 107 */
1637 { KB_NONE, "", "", "", "", ""}, /* 108 */
1638 { KB_NONE, "", "", "", "", ""}, /* 109 */
1639 { KB_NONE, "", "", "", "", ""}, /* 110 */
1640 { KB_NONE, "", "", "", "", ""}, /* 111 */
1641 { KB_NONE, "", "", "", "", ""}, /* 112 */
1642 { KB_NONE, "", "", "", "", ""}, /* 113 */
1643 { KB_NONE, "", "", "", "", ""}, /* 114 */
1644 { KB_NONE, "", "", "", "", ""}, /* 115 */
1645 { KB_NONE, "", "", "", "", ""}, /* 116 */
1646 { KB_NONE, "", "", "", "", ""}, /* 117 */
1647 { KB_NONE, "", "", "", "", ""}, /* 118 */
1648 { KB_NONE, "", "", "", "", ""}, /* 119 */
1649 { KB_NONE, "", "", "", "", ""}, /* 120 */
1650 { KB_NONE, "", "", "", "", ""}, /* 121 */
1651 { KB_NONE, "", "", "", "", ""}, /* 122 */
1652 { KB_NONE, "", "", "", "", ""}, /* 123 */
1653 { KB_NONE, "", "", "", "", ""}, /* 124 */
1654 { KB_NONE, "", "", "", "", ""}, /* 125 */
1655 { KB_NONE, "", "", "", "", ""}, /* 126 */
1656 { KB_NONE, "", "", "", "", ""} /* 127 */
1657 };
1658
1659 /*
1660 * Get characters from the keyboard. If none are present, return NULL.
1661 */
1662 char *
1663 sget()
1664 {
1665 u_char dt;
1666 static u_char extended = 0, shift_state = 0;
1667 static u_char capchar[2];
1668
1669 top:
1670 KBD_DELAY;
1671 dt = inb(kbd_datap);
1672
1673 switch (dt) {
1674 case KBR_ACK: case KBR_ECHO:
1675 kb_oq_get = (kb_oq_get + 1) & 7;
1676 if(kb_oq_get != kb_oq_put) {
1677 outb(kbd_datap, kb_oq[kb_oq_get]);
1678 }
1679 goto loop;
1680 case KBR_RESEND:
1681 outb(kbd_datap, kb_oq[kb_oq_get]);
1682 goto loop;
1683 }
1684
1685 if (pc_xmode > 0) {
1686 #if defined(DDB) && defined(XSERVER_DDB)
1687 /* F12 enters the debugger while in X mode */
1688 if (dt == 88)
1689 Debugger();
1690 #endif
1691 capchar[0] = dt;
1692 capchar[1] = 0;
1693 /*
1694 * Check for locking keys.
1695 *
1696 * XXX Setting the LEDs this way is a bit bogus. What if the
1697 * keyboard has been remapped in X?
1698 */
1699 switch (scan_codes[dt & 0x7f].type) {
1700 case KB_NUM:
1701 if (dt & 0x80) {
1702 shift_state &= ~KB_NUM;
1703 break;
1704 }
1705 if (shift_state & KB_NUM)
1706 break;
1707 shift_state |= KB_NUM;
1708 lock_state ^= KB_NUM;
1709 async_update();
1710 break;
1711 case KB_CAPS:
1712 if (dt & 0x80) {
1713 shift_state &= ~KB_CAPS;
1714 break;
1715 }
1716 if (shift_state & KB_CAPS)
1717 break;
1718 shift_state |= KB_CAPS;
1719 lock_state ^= KB_CAPS;
1720 async_update();
1721 break;
1722 case KB_SCROLL:
1723 if (dt & 0x80) {
1724 shift_state &= ~KB_SCROLL;
1725 break;
1726 }
1727 if (shift_state & KB_SCROLL)
1728 break;
1729 shift_state |= KB_SCROLL;
1730 lock_state ^= KB_SCROLL;
1731 if ((lock_state & KB_SCROLL) == 0)
1732 wakeup((caddr_t)&lock_state);
1733 async_update();
1734 break;
1735 }
1736 return capchar;
1737 }
1738
1739 switch (dt) {
1740 case KBR_EXTENDED:
1741 extended = 1;
1742 goto loop;
1743 }
1744
1745 #ifdef DDB
1746 /*
1747 * Check for cntl-alt-esc.
1748 */
1749 if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
1750 /* XXX - check pccons_is_console */
1751 Debugger();
1752 dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */
1753 }
1754 #endif
1755
1756 /*
1757 * Check for make/break.
1758 */
1759 if (dt & 0x80) {
1760 /*
1761 * break
1762 */
1763 dt &= 0x7f;
1764 switch (scan_codes[dt].type) {
1765 case KB_NUM:
1766 shift_state &= ~KB_NUM;
1767 break;
1768 case KB_CAPS:
1769 shift_state &= ~KB_CAPS;
1770 break;
1771 case KB_SCROLL:
1772 shift_state &= ~KB_SCROLL;
1773 break;
1774 case KB_SHIFT:
1775 shift_state &= ~KB_SHIFT;
1776 break;
1777 case KB_ALT:
1778 if (extended)
1779 shift_state &= ~KB_ALTGR;
1780 else
1781 shift_state &= ~KB_ALT;
1782 break;
1783 case KB_CTL:
1784 shift_state &= ~KB_CTL;
1785 break;
1786 }
1787 } else {
1788 /*
1789 * make
1790 */
1791 switch (scan_codes[dt].type) {
1792 /*
1793 * locking keys
1794 */
1795 case KB_NUM:
1796 if (shift_state & KB_NUM)
1797 break;
1798 shift_state |= KB_NUM;
1799 lock_state ^= KB_NUM;
1800 async_update();
1801 break;
1802 case KB_CAPS:
1803 if (shift_state & KB_CAPS)
1804 break;
1805 shift_state |= KB_CAPS;
1806 lock_state ^= KB_CAPS;
1807 async_update();
1808 break;
1809 case KB_SCROLL:
1810 if (shift_state & KB_SCROLL)
1811 break;
1812 shift_state |= KB_SCROLL;
1813 lock_state ^= KB_SCROLL;
1814 if ((lock_state & KB_SCROLL) == 0)
1815 wakeup((caddr_t)&lock_state);
1816 async_update();
1817 break;
1818 /*
1819 * non-locking keys
1820 */
1821 case KB_SHIFT:
1822 shift_state |= KB_SHIFT;
1823 break;
1824 case KB_ALT:
1825 if (extended)
1826 shift_state |= KB_ALTGR;
1827 else
1828 shift_state |= KB_ALT;
1829 break;
1830 case KB_CTL:
1831 shift_state |= KB_CTL;
1832 break;
1833 case KB_ASCII:
1834 /* control has highest priority */
1835 if (shift_state & KB_CTL)
1836 capchar[0] = scan_codes[dt].ctl[0];
1837 else if (shift_state & KB_ALTGR) {
1838 if (shift_state & KB_SHIFT)
1839 capchar[0] = scan_codes[dt].shift_altgr[0];
1840 else
1841 capchar[0] = scan_codes[dt].altgr[0];
1842 }
1843 else {
1844 if (shift_state & KB_SHIFT)
1845 capchar[0] = scan_codes[dt].shift[0];
1846 else
1847 capchar[0] = scan_codes[dt].unshift[0];
1848 }
1849 if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
1850 capchar[0] <= 'z') {
1851 capchar[0] -= ('a' - 'A');
1852 }
1853 capchar[0] |= (shift_state & KB_ALT);
1854 extended = 0;
1855 return capchar;
1856 case KB_NONE:
1857 printf("keycode %d\n",dt);
1858 break;
1859 case KB_FUNC: {
1860 char *more_chars;
1861 if (shift_state & KB_SHIFT)
1862 more_chars = scan_codes[dt].shift;
1863 else if (shift_state & KB_CTL)
1864 more_chars = scan_codes[dt].ctl;
1865 else
1866 more_chars = scan_codes[dt].unshift;
1867 extended = 0;
1868 return more_chars;
1869 }
1870 case KB_KP: {
1871 char *more_chars;
1872 if (shift_state & (KB_SHIFT | KB_CTL) ||
1873 (lock_state & KB_NUM) == 0 || extended)
1874 more_chars = scan_codes[dt].shift;
1875 else
1876 more_chars = scan_codes[dt].unshift;
1877 extended = 0;
1878 return more_chars;
1879 }
1880 }
1881 }
1882
1883 extended = 0;
1884 loop:
1885 if ((inb(kbd_cmdp) & KBS_DIB) == 0)
1886 return 0;
1887 goto top;
1888 }
1889
1890 int
1891 pcmmap(dev, offset, nprot)
1892 dev_t dev;
1893 int offset;
1894 int nprot;
1895 {
1896
1897 switch(cputype) {
1898
1899 case ACER_PICA_61:
1900 if (offset >= 0xa0000 && offset < 0xc0000)
1901 return mips_btop(PICA_P_LOCAL_VIDEO + offset);
1902 if (offset >= 0x0000 && offset < 0x10000)
1903 return mips_btop(PICA_P_LOCAL_VIDEO_CTRL + offset);
1904 if (offset >= 0x40000000 && offset < 0x40800000)
1905 return mips_btop(PICA_P_LOCAL_VIDEO + offset - 0x40000000);
1906 return -1;
1907
1908 case DESKSTATION_RPC44:
1909 if (offset >= 0xa0000 && offset < 0xc0000)
1910 return mips_btop(RPC44_P_ISA_MEM + offset);
1911 if (offset >= 0x0000 && offset < 0x10000)
1912 return mips_btop(RPC44_P_ISA_IO + offset);
1913 if (offset >= 0x40000000 && offset < 0x40800000)
1914 return mips_btop(RPC44_P_ISA_MEM + offset - 0x40000000);
1915 return -1;
1916
1917 case DESKSTATION_TYNE:
1918 /* Addresses returned are a fake to be able to handle >32 bit
1919 * physical addresses used by the tyne. The real physical adr
1920 * processing is done in pmap.c. Until we are a real 64 bit
1921 * port this is how it will be done.
1922 */
1923 /* XXX - the above is not supported merged pmap, yet */
1924 if (offset >= 0xa0000 && offset < 0xc0000)
1925 return mips_btop(TYNE_V_ISA_MEM + offset);
1926 if (offset >= 0x0000 && offset < 0x10000)
1927 return mips_btop(TYNE_V_ISA_IO + offset);
1928 if (offset >= 0x40000000 && offset < 0x40800000)
1929 return mips_btop(TYNE_V_ISA_MEM + offset - 0x40000000);
1930 return -1;
1931 }
1932 return -1;
1933 }
1934
1935 void
1936 pc_xmode_on()
1937 {
1938 if (pc_xmode)
1939 return;
1940 pc_xmode = 1;
1941
1942 #ifdef XFREE86_BUG_COMPAT
1943 /* If still unchanged, get current shape. */
1944 if (cursor_shape == 0xffff)
1945 get_cursor_shape();
1946 #endif
1947 }
1948
1949 void
1950 pc_xmode_off()
1951 {
1952 if (pc_xmode == 0)
1953 return;
1954 pc_xmode = 0;
1955
1956 #ifdef XFREE86_BUG_COMPAT
1957 /* XXX It would be hard to justify why the X server doesn't do this. */
1958 set_cursor_shape();
1959 #endif
1960 async_update();
1961 }
1962
1963 #include <machine/mouse.h>
1964
1965 /* status bits */
1966 #define PMS_OBUF_FULL 0x01
1967 #define PMS_IBUF_FULL 0x02
1968
1969 /* controller commands */
1970 #define PMS_INT_ENABLE 0x47 /* enable controller interrupts */
1971 #define PMS_INT_DISABLE 0x65 /* disable controller interrupts */
1972 #define PMS_AUX_ENABLE 0xa7 /* enable auxiliary port */
1973 #define PMS_AUX_DISABLE 0xa8 /* disable auxiliary port */
1974 #define PMS_MAGIC_1 0xa9 /* XXX */
1975
1976 #define PMS_8042_CMD 0x65
1977
1978 /* mouse commands */
1979 #define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
1980 #define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
1981 #define PMS_SET_RES 0xe8 /* set resolution */
1982 #define PMS_GET_SCALE 0xe9 /* get scaling factor */
1983 #define PMS_SET_STREAM 0xea /* set streaming mode */
1984 #define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
1985 #define PMS_DEV_ENABLE 0xf4 /* mouse on */
1986 #define PMS_DEV_DISABLE 0xf5 /* mouse off */
1987 #define PMS_RESET 0xff /* reset */
1988
1989 #define PMS_CHUNK 128 /* chunk size for read */
1990 #define PMS_BSIZE 1020 /* buffer size */
1991
1992 #define FLUSHQ(q) { if((q)->c_cc) ndflush(q, (q)->c_cc); }
1993
1994 int opmsopen __P((dev_t, int));
1995 int opmsclose __P((dev_t, int));
1996 int opmsread __P((dev_t, struct uio *, int));
1997 int opmsioctl __P((dev_t, u_long, caddr_t, int));
1998 int opmsselect __P((dev_t, int, struct proc *));
1999 int opmspoll __P((dev_t, int, struct proc *));
2000 static __inline void pms_dev_cmd __P((u_char));
2001 static __inline void pms_aux_cmd __P((u_char));
2002 static __inline void pms_pit_cmd __P((u_char));
2003
2004 static __inline void
2005 pms_dev_cmd(value)
2006 u_char value;
2007 {
2008 kbd_flush_input();
2009 outb(kbd_cmdp, 0xd4);
2010 kbd_flush_input();
2011 outb(kbd_datap, value);
2012 }
2013
2014 static __inline void
2015 pms_aux_cmd(value)
2016 u_char value;
2017 {
2018 kbd_flush_input();
2019 outb(kbd_cmdp, value);
2020 }
2021
2022 static __inline void
2023 pms_pit_cmd(value)
2024 u_char value;
2025 {
2026 kbd_flush_input();
2027 outb(kbd_cmdp, 0x60);
2028 kbd_flush_input();
2029 outb(kbd_datap, value);
2030 }
2031
2032 int
2033 opmsprobe(parent, match, aux)
2034 struct device *parent;
2035 struct cfdata *match;
2036 void *aux;
2037 {
2038 struct confargs *ca = aux;
2039 u_char x;
2040
2041 /* Make shure we're looking for this type of device */
2042 if(!BUS_MATCHNAME(ca, "pms"))
2043 return(0);
2044
2045 pms_dev_cmd(KBC_RESET);
2046 pms_aux_cmd(PMS_MAGIC_1);
2047 delay(10000);
2048 x = inb(kbd_datap);
2049 pms_pit_cmd(PMS_INT_DISABLE);
2050 if (x & 0x04)
2051 return 0;
2052
2053 return 1;
2054 }
2055
2056 void
2057 opmsattach(parent, self, aux)
2058 struct device *parent, *self;
2059 void *aux;
2060 {
2061 struct opms_softc *sc = (void *)self;
2062 struct confargs *ca = aux;
2063
2064 printf("\n");
2065
2066 /* Other initialization was done by opmsprobe. */
2067 sc->sc_state = 0;
2068
2069 BUS_INTR_ESTABLISH(ca, opmsintr, (void *)(long)sc);
2070 }
2071
2072 int
2073 opmsopen(dev, flag)
2074 dev_t dev;
2075 int flag;
2076 {
2077 int unit = PMSUNIT(dev);
2078 struct opms_softc *sc;
2079
2080 if (unit >= opms_cd.cd_ndevs)
2081 return ENXIO;
2082 sc = opms_cd.cd_devs[unit];
2083 if (!sc)
2084 return ENXIO;
2085
2086 if (sc->sc_state & PMS_OPEN)
2087 return EBUSY;
2088
2089 if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
2090 return ENOMEM;
2091
2092 sc->sc_state |= PMS_OPEN;
2093 sc->sc_status = 0;
2094 sc->sc_x = sc->sc_y = 0;
2095
2096 /* Enable interrupts. */
2097 pms_dev_cmd(PMS_DEV_ENABLE);
2098 pms_aux_cmd(PMS_AUX_ENABLE);
2099 pms_dev_cmd(PMS_SET_RES);
2100 pms_dev_cmd(3); /* 8 counts/mm */
2101 pms_dev_cmd(PMS_SET_SCALE21);
2102 #if 0
2103 pms_dev_cmd(PMS_SET_SAMPLE);
2104 pms_dev_cmd(100); /* 100 samples/sec */
2105 pms_dev_cmd(PMS_SET_STREAM);
2106 #endif
2107 pms_pit_cmd(PMS_INT_ENABLE);
2108
2109 return 0;
2110 }
2111
2112 int
2113 opmsclose(dev, flag)
2114 dev_t dev;
2115 int flag;
2116 {
2117 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2118
2119 /* Disable interrupts. */
2120 pms_dev_cmd(PMS_DEV_DISABLE);
2121 pms_pit_cmd(PMS_INT_DISABLE);
2122 pms_aux_cmd(PMS_AUX_DISABLE);
2123
2124 sc->sc_state &= ~PMS_OPEN;
2125
2126 clfree(&sc->sc_q);
2127
2128 return 0;
2129 }
2130
2131 int
2132 opmsread(dev, uio, flag)
2133 dev_t dev;
2134 struct uio *uio;
2135 int flag;
2136 {
2137 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2138 int s;
2139 int error = 0;
2140 size_t length;
2141 u_char buffer[PMS_CHUNK];
2142
2143 /* Block until mouse activity occured. */
2144
2145 s = spltty();
2146 while (sc->sc_q.c_cc == 0) {
2147 if (flag & IO_NDELAY) {
2148 splx(s);
2149 return EWOULDBLOCK;
2150 }
2151 sc->sc_state |= PMS_ASLP;
2152 error = tsleep((caddr_t)sc, PZERO | PCATCH, "pmsrea", 0);
2153 if (error) {
2154 sc->sc_state &= ~PMS_ASLP;
2155 splx(s);
2156 return error;
2157 }
2158 }
2159 splx(s);
2160
2161 /* Transfer as many chunks as possible. */
2162
2163 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
2164 length = min(sc->sc_q.c_cc, uio->uio_resid);
2165 if (length > sizeof(buffer))
2166 length = sizeof(buffer);
2167
2168 /* Remove a small chunk from the input queue. */
2169 (void) q_to_b(&sc->sc_q, buffer, length);
2170
2171 /* Copy the data to the user process. */
2172 error = uiomove(buffer, length, uio);
2173 if (error)
2174 break;
2175 }
2176
2177 return error;
2178 }
2179
2180 int
2181 opmsioctl(dev, cmd, addr, flag)
2182 dev_t dev;
2183 u_long cmd;
2184 caddr_t addr;
2185 int flag;
2186 {
2187 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2188 struct mouseinfo info;
2189 int s;
2190 int error;
2191
2192 switch (cmd) {
2193 case MOUSEIOCREAD:
2194 s = spltty();
2195
2196 info.status = sc->sc_status;
2197 if (sc->sc_x || sc->sc_y)
2198 info.status |= MOVEMENT;
2199
2200 if (sc->sc_x > 127)
2201 info.xmotion = 127;
2202 else if (sc->sc_x < -127)
2203 /* Bounding at -127 avoids a bug in XFree86. */
2204 info.xmotion = -127;
2205 else
2206 info.xmotion = sc->sc_x;
2207
2208 if (sc->sc_y > 127)
2209 info.ymotion = 127;
2210 else if (sc->sc_y < -127)
2211 info.ymotion = -127;
2212 else
2213 info.ymotion = sc->sc_y;
2214
2215 /* Reset historical information. */
2216 sc->sc_x = sc->sc_y = 0;
2217 sc->sc_status &= ~BUTCHNGMASK;
2218 ndflush(&sc->sc_q, sc->sc_q.c_cc);
2219
2220 splx(s);
2221 error = copyout(&info, addr, sizeof(struct mouseinfo));
2222 break;
2223 default:
2224 error = EINVAL;
2225 break;
2226 }
2227
2228 return error;
2229 }
2230
2231 /* Masks for the first byte of a packet */
2232 #define PS2LBUTMASK 0x01
2233 #define PS2RBUTMASK 0x02
2234 #define PS2MBUTMASK 0x04
2235
2236 int
2237 opmsintr(arg)
2238 void *arg;
2239 {
2240 struct opms_softc *sc = arg;
2241 static int state = 0;
2242 static u_char buttons;
2243 u_char changed;
2244 static char dx, dy;
2245 u_char buffer[5];
2246
2247 if ((sc->sc_state & PMS_OPEN) == 0) {
2248 /* Interrupts are not expected. Discard the byte. */
2249 kbd_flush_input();
2250 return 0;
2251 }
2252
2253 switch (state) {
2254
2255 case 0:
2256 buttons = inb(kbd_datap);
2257 if ((buttons & 0xc0) == 0)
2258 ++state;
2259 break;
2260
2261 case 1:
2262 dx = inb(kbd_datap);
2263 /* Bounding at -127 avoids a bug in XFree86. */
2264 dx = (dx == -128) ? -127 : dx;
2265 ++state;
2266 break;
2267
2268 case 2:
2269 dy = inb(kbd_datap);
2270 dy = (dy == -128) ? -127 : dy;
2271 state = 0;
2272
2273 buttons = ((buttons & PS2LBUTMASK) << 2) |
2274 ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
2275 changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
2276 sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
2277
2278 if (dx || dy || changed) {
2279 /* Update accumulated movements. */
2280 sc->sc_x += dx;
2281 sc->sc_y += dy;
2282
2283 /* Add this event to the queue. */
2284 buffer[0] = 0x80 | (buttons & BUTSTATMASK);
2285 if(dx < 0)
2286 buffer[0] |= 0x10;
2287 buffer[1] = dx & 0x7f;
2288 if(dy < 0)
2289 buffer[0] |= 0x20;
2290 buffer[2] = dy & 0x7f;
2291 buffer[3] = buffer[4] = 0;
2292 (void) b_to_q(buffer, sizeof buffer, &sc->sc_q);
2293
2294 if (sc->sc_state & PMS_ASLP) {
2295 sc->sc_state &= ~PMS_ASLP;
2296 wakeup((caddr_t)sc);
2297 }
2298 selwakeup(&sc->sc_rsel);
2299 }
2300
2301 break;
2302 }
2303 return -1;
2304 }
2305
2306 int
2307 opmspoll(dev, events, p)
2308 dev_t dev;
2309 int events;
2310 struct proc *p;
2311 {
2312 struct opms_softc *sc = opms_cd.cd_devs[PMSUNIT(dev)];
2313 int revents = 0;
2314 int s = spltty();
2315
2316 if (events & (POLLIN | POLLRDNORM))
2317 if (sc->sc_q.c_cc > 0)
2318 revents |= events & (POLLIN | POLLRDNORM);
2319 else
2320 selrecord(p, &sc->sc_rsel);
2321
2322 splx(s);
2323 return (revents);
2324 }
2325