BIOS.MousePS2.Mod 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE MousePS2; (** AUTHOR "pjm"; PURPOSE "PS/2 mouse driver"; *)
  3. (*
  4. Mouse protocol information from XFree in X11R6 distribution (Thomas Roell & David Dawes)
  5. PS/2 Aux port information from Linux (Johan Myreen et al.)
  6. *)
  7. IMPORT SYSTEM, Machine, Modules, Objects, Kernel, Inputs;
  8. TYPE
  9. Aux = OBJECT
  10. VAR
  11. p, numb: LONGINT;
  12. buf: ARRAY 4 OF SET;
  13. active: BOOLEAN;
  14. timer: Objects.Timer;
  15. PROCEDURE HandleInterrupt;
  16. VAR b: SET; m: Inputs.MouseMsg; ch: CHAR;
  17. BEGIN {EXCLUSIVE}
  18. Machine.Portin8(64H, ch); (* check for valid data *)
  19. IF SYSTEM.VAL(SET, ch) * {0} = {} THEN INC(ignored); RETURN END;
  20. Machine.Portin8(60H, ch); (* read byte *)
  21. IF active THEN
  22. b := SYSTEM.VAL(SET, LONG(ORD(ch)));
  23. IF (p = 0) & (b * {6,7} # {}) THEN (* skip package *)
  24. INC(errors)
  25. ELSE
  26. buf[p] := b; INC(p);
  27. IF p = numb THEN
  28. m.keys := {};
  29. IF 2 IN buf[0] THEN INCL(m.keys, 1) END;
  30. IF 1 IN buf[0] THEN INCL(m.keys, 2) END;
  31. IF 0 IN buf[0] THEN INCL(m.keys, 0) END;
  32. m.dx := SYSTEM.VAL(LONGINT, buf[1]);
  33. IF 4 IN buf[0] THEN DEC(m.dx, 256) END;
  34. m.dy := SYSTEM.VAL(LONGINT, buf[2]);
  35. IF 5 IN buf[0] THEN DEC(m.dy, 256) END;
  36. m.dz := SYSTEM.VAL(SHORTINT, buf[3]);
  37. IF 6 IN buf[0] THEN DEC(m.dz, 256) END;
  38. p := 0; m.dy := -m.dy;
  39. Inputs.mouse.Handle(m)
  40. END
  41. END
  42. ELSE
  43. INC(ignored)
  44. END
  45. END HandleInterrupt;
  46. PROCEDURE HandleTimeout;
  47. BEGIN {EXCLUSIVE}
  48. active := TRUE
  49. END HandleTimeout;
  50. PROCEDURE &Init*(rate: LONGINT);
  51. PROCEDURE SetRate(r: LONGINT);
  52. BEGIN WriteAck(0F3X); WriteAck(CHR(r))
  53. END SetRate;
  54. BEGIN
  55. active := FALSE; p := 0;
  56. PollAux;
  57. Machine.Portout8(64H, 0A8X); (* enable aux *)
  58. (* enable MS Intellimouse 3rd button *)
  59. SetRate(200); SetRate(100); SetRate(80); SetRate(rate);
  60. WriteAck(0F2X);
  61. IF InAux() # 0X THEN numb := 4 ELSE numb := 3 END; (* Ident *)
  62. WriteAck(0E8X); WriteAck(3X); (* 8 counts/mm *)
  63. WriteAck(0E7X); (* 2:1 scale *)
  64. PollAux;
  65. Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+12);
  66. WriteDev(0F4X); (* enable aux device *)
  67. WriteCmd(47X); (* controller interrupts on *)
  68. PollAux;
  69. NEW(timer); Objects.SetTimeout(timer, SELF.HandleTimeout, 250) (* ignore bytes in first 1/4s *)
  70. END Init;
  71. PROCEDURE Remove;
  72. BEGIN {EXCLUSIVE}
  73. Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0+12);
  74. Objects.CancelTimeout(timer)
  75. END Remove;
  76. END Aux;
  77. VAR
  78. errors*, ignored*: LONGINT; (* diagnostic counters *)
  79. aux: Aux;
  80. PROCEDURE PollAux;
  81. VAR s: SET; i: LONGINT; t: Kernel.MilliTimer;
  82. BEGIN
  83. i := 10; (* up to 0.2s! *)
  84. LOOP
  85. Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
  86. IF (s * {0,1} = {}) OR (i = 0) THEN EXIT END;
  87. Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
  88. IF s * {0,5} = {0,5} THEN Machine.Portin8(60H, SYSTEM.VAL(CHAR, s)) END; (* byte avail *)
  89. Kernel.SetTimer(t, 20); (* 20ms *)
  90. REPEAT UNTIL Kernel.Expired(t);
  91. DEC(i)
  92. END
  93. END PollAux;
  94. PROCEDURE InAux(): CHAR;
  95. VAR s: SET; t: Kernel.MilliTimer;ch: CHAR; i: SHORTINT;
  96. BEGIN
  97. i := 10; (* up to 0.2s! *)
  98. REPEAT
  99. Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
  100. IF s * {0,5} = {0,5} THEN (* byte avail *)
  101. Machine.Portin8(60H, ch);
  102. RETURN ch
  103. END;
  104. Kernel.SetTimer(t, 20);
  105. REPEAT UNTIL Kernel.Expired(t);
  106. DEC(i);
  107. UNTIL i = 0;
  108. RETURN 0X
  109. END InAux;
  110. PROCEDURE WriteDev(b: CHAR);
  111. BEGIN
  112. PollAux; Machine.Portout8(64H, 0D4X); (* aux data coming *)
  113. PollAux; Machine.Portout8(60H, b)
  114. END WriteDev;
  115. PROCEDURE WriteAck(b: CHAR);
  116. VAR s: SET; i: LONGINT; t: Kernel.MilliTimer;
  117. BEGIN
  118. WriteDev(b); i := 10; (* up to 0.2s! *)
  119. LOOP
  120. Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
  121. IF (s * {0,5} = {0,5}) OR (i = 0) THEN EXIT END;
  122. Kernel.SetTimer(t, 20); (* 20ms *)
  123. REPEAT UNTIL Kernel.Expired(t);
  124. DEC(i)
  125. END;
  126. IF i # 0 THEN Machine.Portin8(60H, SYSTEM.VAL(CHAR, s)) END (* byte avail *)
  127. END WriteAck;
  128. PROCEDURE WriteCmd(b: CHAR);
  129. BEGIN
  130. PollAux; Machine.Portout8(64H, 60X);
  131. PollAux; Machine.Portout8(60H, b)
  132. END WriteCmd;
  133. PROCEDURE ConfigMouse;
  134. VAR i, rate: LONGINT; s: ARRAY 16 OF CHAR;
  135. BEGIN
  136. errors := 0; ignored := 0;
  137. Machine.GetConfig("MouseRate", s);
  138. i := 0; rate := Machine.StrToInt(i, s);
  139. IF (rate <= 0) OR (rate > 150) THEN rate := 100 END;
  140. NEW(aux, rate)
  141. END ConfigMouse;
  142. PROCEDURE Install*;
  143. BEGIN
  144. IF aux = NIL THEN ConfigMouse END
  145. END Install;
  146. PROCEDURE Remove*;
  147. BEGIN
  148. IF aux # NIL THEN aux.Remove(); aux := NIL END
  149. END Remove;
  150. BEGIN
  151. Modules.InstallTermHandler(Remove);
  152. aux := NIL; Install
  153. END MousePS2.