PageRenderTime 67ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/base/Kernel/Singularity.Hal.LegacyPC/HalScreenDirect.cs

#
C# | 342 lines | 271 code | 48 blank | 23 comment | 39 complexity | 314356007e431cbcd5aa2482ad01f48e MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // File: HalScreenDirect.cs
  8. //
  9. // Note:
  10. // The Indispensable PC Hardware Book (Third Edition), pp1055-1066.
  11. using System;
  12. using System.Runtime.CompilerServices;
  13. using Microsoft.Singularity.Channels;
  14. using Microsoft.Singularity.Io;
  15. using Microsoft.Singularity.Configuration;
  16. [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
  17. [assembly: System.Reflection.AssemblyKeyFileAttribute(@"..\public.snk")]
  18. [assembly: System.Reflection.AssemblyDelaySignAttribute(true)]
  19. namespace Microsoft.Singularity.Hal
  20. {
  21. // declare resources for the kernel manifest
  22. [DriverCategory]
  23. public sealed class HalScreenResources : DriverCategoryDeclaration
  24. {
  25. [IoFixedPortRange(Base = 0x03d4, Length = 0x01, Shared = true)]
  26. public IoPortRange indexPort;
  27. [IoFixedPortRange(Base = 0x03d5, Length = 0x01, Shared = true)]
  28. public IoPortRange dataPort;
  29. [IoFixedMemoryRange(Base = 0xb8000, Length = 8000, Shared = true)]
  30. public IoMemoryRange screenMemory;
  31. // TODO: how can we represent endpoints here?
  32. //[ServiceEndpoint(typeof(ConsoleDeviceContract.Exp),
  33. // CustomName = "HalScreen")]
  34. //TRef<ServiceProviderContract.Exp:Start> conoutsp;
  35. }
  36. [CLSCompliant(false)]
  37. public class HalScreenDirect : HalScreen
  38. {
  39. public const int Columns = 80;
  40. public const int Rows = 50;
  41. public const int ScreenSize = Columns * Rows;
  42. public const ushort CGA_INDEX_PORT = 0x3d4;
  43. public const ushort CGA_DATA_PORT = 0x3d5;
  44. public const byte SmallCursorStart = 6;
  45. public const byte LargeCursorStart = 0;
  46. private enum Coloring
  47. {
  48. Dim = 0x1700,
  49. Yellow = 0x1e00,
  50. Green = 0x1a00,
  51. Red = 0x1c00,
  52. Normal = 0x1f00
  53. }
  54. private ushort color = (ushort)Coloring.Normal;
  55. private int cursor = 0;
  56. private bool cursorVisible = false;
  57. private byte cursorStartLine = SmallCursorStart;
  58. private const byte CGA_CURSOR_START = 0xa;
  59. private const byte CGA_CURSOR_MSB = 0xe;
  60. private const byte CGA_CURSOR_LSB = 0xf;
  61. private IoPort indexRegister = null;
  62. private IoPort dataRegister = null;
  63. private IoMemory screenBuffer = null;
  64. public HalScreenDirect(IoConfig config)
  65. {
  66. indexRegister =
  67. ((IoPortRange) config.FixedRanges[0]).PortAtOffset(
  68. 0, 1, Access.Write);
  69. dataRegister =
  70. ((IoPortRange) config.FixedRanges[1]).PortAtOffset(
  71. 0, 1, Access.Write);
  72. screenBuffer =
  73. ((IoMemoryRange) config.FixedRanges[2]).MemoryAtOffset(
  74. 0, ScreenSize * 2, Access.ReadWrite);
  75. Clear();
  76. WriteLine("Singularity HAL Console Driver.");
  77. UpdateCursor(true);
  78. }
  79. public HalScreenDirect()
  80. {
  81. // For compatibility with .csi compiled file
  82. DebugStub.Break();
  83. }
  84. [NoHeapAllocation]
  85. public void Dim()
  86. {
  87. color = (ushort)Coloring.Dim;
  88. }
  89. [NoHeapAllocation]
  90. public void Yellow()
  91. {
  92. color = (ushort)Coloring.Yellow;
  93. }
  94. [NoHeapAllocation]
  95. public void Green()
  96. {
  97. color = (ushort)Coloring.Green;
  98. }
  99. [NoHeapAllocation]
  100. public void Red()
  101. {
  102. color = (ushort)Coloring.Red;
  103. }
  104. [NoHeapAllocation]
  105. public void Normal()
  106. {
  107. color = (ushort)Coloring.Normal;
  108. }
  109. [NoHeapAllocation]
  110. public override void CursorFlash()
  111. {
  112. ushort was;
  113. screenBuffer.Read16NoThrow(0, out was);
  114. was &= (ushort)0xff00;
  115. screenBuffer.Write16NoThrow(0, was);
  116. }
  117. [NoHeapAllocation]
  118. public override void CursorHide()
  119. {
  120. UpdateCursor(false);
  121. }
  122. [NoHeapAllocation]
  123. public override void CursorShow()
  124. {
  125. UpdateCursor(true);
  126. }
  127. [NoHeapAllocation]
  128. public override void Clear()
  129. {
  130. if (screenBuffer == null) {
  131. DebugStub.Break();
  132. return;
  133. }
  134. ushort zip = (ushort)(color | ' ');
  135. IoResult result = screenBuffer.Write16NoThrow(0, zip, ScreenSize);
  136. DebugStub.Assert(IoResult.Success == result);
  137. cursor = 0;
  138. UpdateCursor(cursorVisible);
  139. }
  140. [NoHeapAllocation]
  141. public override void GetDisplayDimensions(out int columns, out int rows)
  142. {
  143. columns = Columns;
  144. rows = Rows;
  145. }
  146. [NoHeapAllocation]
  147. public override void GetCursorPosition(out int column, out int row)
  148. {
  149. column = cursor % Columns;
  150. row = cursor / Columns;
  151. }
  152. [NoHeapAllocation]
  153. public override void SetCursorSizeLarge()
  154. {
  155. cursorStartLine = LargeCursorStart;
  156. ForcedCursorUpdate();
  157. }
  158. [NoHeapAllocation]
  159. public override void SetCursorSizeSmall()
  160. {
  161. cursorStartLine = SmallCursorStart;
  162. ForcedCursorUpdate();
  163. }
  164. [NoHeapAllocation]
  165. private void ForcedCursorUpdate()
  166. {
  167. bool saved = cursorVisible;
  168. cursorVisible = !cursorVisible;
  169. UpdateCursor(saved);
  170. }
  171. [NoHeapAllocation]
  172. private void UpdateCursor(bool newVisibleState)
  173. {
  174. IoResult result;
  175. if (newVisibleState != cursorVisible) {
  176. byte cgaStart = 32; // Cursor off
  177. if (newVisibleState) {
  178. cgaStart = (byte)(64 + cursorStartLine); // Cursor on
  179. }
  180. result = indexRegister.Write8NoThrow(CGA_CURSOR_START);
  181. DebugStub.Assert(IoResult.Success == result);
  182. result = dataRegister.Write8NoThrow(cgaStart);
  183. DebugStub.Assert(IoResult.Success == result);
  184. cursorVisible = newVisibleState;
  185. }
  186. if (newVisibleState) {
  187. // Write cursor location
  188. result = indexRegister.Write8NoThrow(CGA_CURSOR_MSB);
  189. DebugStub.Assert(IoResult.Success == result);
  190. result = dataRegister.Write8NoThrow((byte)(cursor >> 8));
  191. DebugStub.Assert(IoResult.Success == result);
  192. result = indexRegister.Write8NoThrow(CGA_CURSOR_LSB);
  193. DebugStub.Assert(IoResult.Success == result);
  194. result = dataRegister.Write8NoThrow((byte)(cursor & 0xff));
  195. DebugStub.Assert(IoResult.Success == result);
  196. }
  197. }
  198. [NoHeapAllocation]
  199. public override bool SetCursorPosition(int column, int row)
  200. {
  201. if (column < 0 || column >= Columns ||
  202. row < 0 || row >= Rows) {
  203. return false;
  204. }
  205. cursor = column + row * Columns;
  206. UpdateCursor(cursorVisible);
  207. return true;
  208. }
  209. [NoHeapAllocation]
  210. public override void ClearCursorToEndOfLine()
  211. {
  212. // Writing to the screen is slow. We might
  213. // want to track how many characters are written per line
  214. // to speed this up.
  215. int column = cursor % Columns;
  216. int row = cursor / Columns;
  217. while (column != Columns) {
  218. PutCharAt(' ', column++, row);
  219. }
  220. }
  221. [NoHeapAllocation]
  222. public override bool PutCharAt(char c, int column, int row)
  223. {
  224. if (column < 0 || column >= Columns ||
  225. row < 0 || row >= Rows) {
  226. return false;
  227. }
  228. int offset = (column + row * Columns) * 2;
  229. IoResult result = screenBuffer.Write16NoThrow(offset,
  230. (ushort)(color | c));
  231. DebugStub.Assert(IoResult.Success == result);
  232. return true;
  233. }
  234. [NoHeapAllocation]
  235. public override void PutChar(char c)
  236. {
  237. PutChar((byte)c);
  238. }
  239. [NoHeapAllocation]
  240. public void PutChar(byte c)
  241. {
  242. if (screenBuffer == null) {
  243. return;
  244. }
  245. if (c == (byte)'\b') {
  246. cursor--;
  247. }
  248. else if (c == (byte)'\r') {
  249. int left = Columns - (cursor % Columns);
  250. cursor -= cursor % Columns;
  251. }
  252. else if (c == (byte)'\n') {
  253. cursor += Columns - (cursor % Columns);
  254. }
  255. else {
  256. IoResult result =
  257. screenBuffer.Write16NoThrow(cursor++ * 2,
  258. (ushort)(color | (c & 0x7f)));
  259. DebugStub.Assert(IoResult.Success == result);
  260. }
  261. if (cursor >= ScreenSize) {
  262. IoResult result;
  263. // Scroll up 1-line
  264. result = screenBuffer.Copy8NoThrow(Columns * 2, 0,
  265. (ScreenSize - Columns) * 2);
  266. DebugStub.Assert(IoResult.Success == result);
  267. // Blank bottom line
  268. result =
  269. screenBuffer.Write16NoThrow((ScreenSize - Columns) * 2,
  270. (ushort)(color | ' '),
  271. Columns);
  272. DebugStub.Assert(IoResult.Success == result);
  273. // Reel in cursor
  274. cursor -= Columns;
  275. }
  276. UpdateCursor(cursorVisible);
  277. }
  278. [NoHeapAllocation]
  279. public override void Write(byte[] buffer, int offset, int count)
  280. {
  281. for (int i = 0; i < count; i++) {
  282. PutChar(buffer[offset + i]);
  283. }
  284. }
  285. private void WriteLine(String value)
  286. {
  287. for (int i = 0; i < value.Length; i++) {
  288. PutChar((byte)value[i]);
  289. }
  290. PutChar((byte)'\r');
  291. PutChar((byte)'\n');
  292. }
  293. }
  294. } // namespace Microsoft.Singularity.Hal