printk.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. //
  2. // Created by longjin on 2022/1/22.
  3. //
  4. #include "printk.h"
  5. #include "kprint.h"
  6. #include <driver/multiboot2/multiboot2.h>
  7. #include <mm/mm.h>
  8. #include <process/spinlock.h>
  9. #include <driver/uart/uart.h>
  10. #include <driver/video/video.h>
  11. #include "math.h"
  12. //#include "linkage.h"
  13. struct printk_screen_info pos;
  14. extern ul VBE_FB_phys_addr; // 由bootloader传来的帧缓存区的物理地址
  15. static spinlock_t printk_lock;
  16. static bool sw_show_scroll_animation = false; // 显示换行动画的开关
  17. int calculate_max_charNum(int len, int size)
  18. {
  19. /**
  20. * @brief 计算屏幕上能有多少行
  21. * @param len 屏幕长/宽
  22. * @param size 字符长/宽
  23. */
  24. return len / size - 1;
  25. }
  26. int printk_init(const int char_size_x, const int char_size_y)
  27. {
  28. struct multiboot_tag_framebuffer_info_t info;
  29. int reserved;
  30. multiboot2_iter(multiboot2_get_Framebuffer_info, &info, &reserved);
  31. pos.width = info.framebuffer_width;
  32. pos.height = info.framebuffer_height;
  33. pos.char_size_x = char_size_x;
  34. pos.char_size_y = char_size_y;
  35. pos.max_x = calculate_max_charNum(pos.width, char_size_x);
  36. pos.max_y = calculate_max_charNum(pos.height, char_size_y);
  37. VBE_FB_phys_addr = (ul)info.framebuffer_addr;
  38. pos.FB_address = (uint *)0xffff800003000000;
  39. pos.FB_length = 1UL * pos.width * pos.height;
  40. // 初始化自旋锁
  41. spin_init(&printk_lock);
  42. // ======== 临时的将物理地址填写到0x0000000003000000处 之后会在mm内将帧缓存区重新映射=====
  43. ul global_CR3 = (ul)get_CR3();
  44. ul fb_virt_addr = (ul)pos.FB_address;
  45. ul fb_phys_addr = VBE_FB_phys_addr;
  46. // 计算帧缓冲区的线性地址对应的pml4页表项的地址
  47. ul *tmp = phys_2_virt((ul *)((ul)global_CR3 & (~0xfffUL)) + ((fb_virt_addr >> PAGE_GDT_SHIFT) & 0x1ff));
  48. tmp = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + ((fb_virt_addr >> PAGE_1G_SHIFT) & 0x1ff));
  49. ul *tmp1;
  50. // 初始化2M物理页
  51. for (ul i = 0; i < (pos.FB_length << 2); i += PAGE_2M_SIZE)
  52. {
  53. // 计算当前2M物理页对应的pdt的页表项的物理地址
  54. tmp1 = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + (((fb_virt_addr + i) >> PAGE_2M_SHIFT) & 0x1ff));
  55. // 页面写穿,禁止缓存
  56. set_pdt(tmp1, mk_pdt((ul)fb_phys_addr + i, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD));
  57. }
  58. flush_tlb();
  59. pos.x = 0;
  60. pos.y = 0;
  61. cls();
  62. kdebug("width=%d\theight=%d", pos.width, pos.height);
  63. // 由于此时系统并未启用双缓冲,因此关闭滚动动画
  64. printk_disable_animation();
  65. return 0;
  66. }
  67. int set_printk_pos(const int x, const int y)
  68. {
  69. // 指定的坐标不在屏幕范围内
  70. if (!((x >= 0 && x <= pos.max_x) && (y >= 0 && y <= pos.max_y)))
  71. return EPOS_OVERFLOW;
  72. pos.x = x;
  73. pos.y = y;
  74. return 0;
  75. }
  76. int skip_and_atoi(const char **s)
  77. {
  78. /**
  79. * @brief 获取连续的一段字符对应整数的值
  80. * @param:**s 指向 指向字符串的指针 的指针
  81. */
  82. int ans = 0;
  83. while (is_digit(**s))
  84. {
  85. ans = ans * 10 + (**s) - '0';
  86. ++(*s);
  87. }
  88. return ans;
  89. }
  90. void auto_newline()
  91. {
  92. /**
  93. * @brief 超过每行最大字符数,自动换行
  94. *
  95. */
  96. if (pos.x > pos.max_x)
  97. {
  98. #ifdef DEBUG
  99. uart_send(COM1, '\r');
  100. uart_send(COM1, '\n');
  101. #endif
  102. pos.x = 0;
  103. ++pos.y;
  104. }
  105. if (pos.y > pos.max_y)
  106. {
  107. #ifdef DEBUG
  108. uart_send(COM1, '\r');
  109. uart_send(COM1, '\n');
  110. #endif
  111. pos.y = pos.max_y;
  112. int lines_to_scroll = 1;
  113. scroll(true, lines_to_scroll * pos.char_size_y, sw_show_scroll_animation);
  114. pos.y -= (lines_to_scroll - 1);
  115. }
  116. }
  117. static int vsprintf(char *buf, const char *fmt, va_list args)
  118. {
  119. /**
  120. * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
  121. * @param buf 结果缓冲区
  122. * @param fmt 格式化字符串
  123. * @param args 内容
  124. * @return 最终字符串的长度
  125. */
  126. char *str, *s;
  127. str = buf;
  128. int flags; // 用来存储格式信息的bitmap
  129. int field_width; //区域宽度
  130. int precision; //精度
  131. int qualifier; //数据显示的类型
  132. int len;
  133. //开始解析字符串
  134. for (; *fmt; ++fmt)
  135. {
  136. //内容不涉及到格式化,直接输出
  137. if (*fmt != '%')
  138. {
  139. *str = *fmt;
  140. ++str;
  141. continue;
  142. }
  143. //开始格式化字符串
  144. //清空标志位和field宽度
  145. field_width = flags = 0;
  146. bool flag_tmp = true;
  147. bool flag_break = false;
  148. ++fmt;
  149. while (flag_tmp)
  150. {
  151. switch (*fmt)
  152. {
  153. case '\0':
  154. //结束解析
  155. flag_break = true;
  156. flag_tmp = false;
  157. break;
  158. case '-':
  159. // 左对齐
  160. flags |= LEFT;
  161. ++fmt;
  162. break;
  163. case '+':
  164. //在正数前面显示加号
  165. flags |= PLUS;
  166. ++fmt;
  167. break;
  168. case ' ':
  169. flags |= SPACE;
  170. ++fmt;
  171. break;
  172. case '#':
  173. //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
  174. flags |= SPECIAL;
  175. ++fmt;
  176. break;
  177. case '0':
  178. //显示的数字之前填充‘0’来取代空格
  179. flags |= PAD_ZERO;
  180. ++fmt;
  181. break;
  182. default:
  183. flag_tmp = false;
  184. break;
  185. }
  186. }
  187. if (flag_break)
  188. break;
  189. //获取区域宽度
  190. field_width = -1;
  191. if (*fmt == '*')
  192. {
  193. field_width = va_arg(args, int);
  194. ++fmt;
  195. }
  196. else if (is_digit(*fmt))
  197. {
  198. field_width = skip_and_atoi(&fmt);
  199. if (field_width < 0)
  200. {
  201. field_width = -field_width;
  202. flags |= LEFT;
  203. }
  204. }
  205. //获取小数精度
  206. precision = -1;
  207. if (*fmt == '.')
  208. {
  209. ++fmt;
  210. if (*fmt == '*')
  211. {
  212. precision = va_arg(args, int);
  213. ++fmt;
  214. }
  215. else if is_digit (*fmt)
  216. {
  217. precision = skip_and_atoi(&fmt);
  218. }
  219. }
  220. //获取要显示的数据的类型
  221. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z')
  222. {
  223. qualifier = *fmt;
  224. ++fmt;
  225. }
  226. //为了支持lld
  227. if (qualifier == 'l' && *fmt == 'l', *(fmt + 1) == 'd')
  228. ++fmt;
  229. //转化成字符串
  230. long long *ip;
  231. switch (*fmt)
  232. {
  233. //输出 %
  234. case '%':
  235. *str++ = '%';
  236. break;
  237. // 显示一个字符
  238. case 'c':
  239. //靠右对齐
  240. if (!(flags & LEFT))
  241. {
  242. while (--field_width > 0)
  243. {
  244. *str = ' ';
  245. ++str;
  246. }
  247. }
  248. *str++ = (unsigned char)va_arg(args, int);
  249. while (--field_width > 0)
  250. {
  251. *str = ' ';
  252. ++str;
  253. }
  254. break;
  255. //显示一个字符串
  256. case 's':
  257. s = va_arg(args, char *);
  258. if (!s)
  259. s = '\0';
  260. len = strlen(s);
  261. if (precision < 0)
  262. {
  263. //未指定精度
  264. precision = len;
  265. }
  266. else if (len > precision)
  267. {
  268. len = precision;
  269. }
  270. //靠右对齐
  271. if (!(flags & LEFT))
  272. while (len < field_width--)
  273. {
  274. *str = ' ';
  275. ++str;
  276. }
  277. for (int i = 0; i < len; i++)
  278. {
  279. *str = *s;
  280. ++s;
  281. ++str;
  282. }
  283. while (len < field_width--)
  284. {
  285. *str = ' ';
  286. ++str;
  287. }
  288. break;
  289. //以八进制显示字符串
  290. case 'o':
  291. flags |= SMALL;
  292. case 'O':
  293. flags |= SPECIAL;
  294. if (qualifier == 'l')
  295. str = write_num(str, va_arg(args, long long), 8, field_width, precision, flags);
  296. else
  297. str = write_num(str, va_arg(args, int), 8, field_width, precision, flags);
  298. break;
  299. //打印指针指向的地址
  300. case 'p':
  301. if (field_width == 0)
  302. {
  303. field_width = 2 * sizeof(void *);
  304. flags |= PAD_ZERO;
  305. }
  306. str = write_num(str, (unsigned long)va_arg(args, void *), 16, field_width, precision, flags);
  307. break;
  308. //打印十六进制
  309. case 'x':
  310. flags |= SMALL;
  311. case 'X':
  312. // flags |= SPECIAL;
  313. if (qualifier == 'l')
  314. str = write_num(str, va_arg(args, ll), 16, field_width, precision, flags);
  315. else
  316. str = write_num(str, va_arg(args, int), 16, field_width, precision, flags);
  317. break;
  318. //打印十进制有符号整数
  319. case 'i':
  320. case 'd':
  321. flags |= SIGN;
  322. if (qualifier == 'l')
  323. str = write_num(str, va_arg(args, long long), 10, field_width, precision, flags);
  324. else
  325. str = write_num(str, va_arg(args, int), 10, field_width, precision, flags);
  326. break;
  327. //打印十进制无符号整数
  328. case 'u':
  329. if (qualifier == 'l')
  330. str = write_num(str, va_arg(args, unsigned long long), 10, field_width, precision, flags);
  331. else
  332. str = write_num(str, va_arg(args, unsigned int), 10, field_width, precision, flags);
  333. break;
  334. //输出有效字符数量到*ip对应的变量
  335. case 'n':
  336. if (qualifier == 'l')
  337. ip = va_arg(args, long long *);
  338. else
  339. ip = (ll *)va_arg(args, int *);
  340. *ip = str - buf;
  341. break;
  342. case 'f':
  343. // 默认精度为3
  344. // printk("1111\n");
  345. // va_arg(args, double);
  346. // printk("222\n");
  347. if (precision < 0)
  348. precision = 3;
  349. str = write_float_point_num(str, va_arg(args, double), field_width, precision, flags);
  350. break;
  351. //对于不识别的控制符,直接输出
  352. default:
  353. *str++ = '%';
  354. if (*fmt)
  355. *str++ = *fmt;
  356. else
  357. --fmt;
  358. break;
  359. }
  360. }
  361. *str = '\0';
  362. //返回缓冲区已有字符串的长度。
  363. return str - buf;
  364. }
  365. static char *write_num(char *str, ul num, int base, int field_width, int precision, int flags)
  366. {
  367. /**
  368. * @brief 将数字按照指定的要求转换成对应的字符串
  369. *
  370. * @param str 要返回的字符串
  371. * @param num 要打印的数值
  372. * @param base 基数
  373. * @param field_width 区域宽度
  374. * @param precision 精度
  375. * @param flags 标志位
  376. */
  377. // 首先判断是否支持该进制
  378. if (base < 2 || base > 36)
  379. return 0;
  380. char pad, sign, tmp_num[100];
  381. const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  382. // 显示小写字母
  383. if (flags & SMALL)
  384. digits = "0123456789abcdefghijklmnopqrstuvwxyz";
  385. if (flags & LEFT)
  386. flags &= ~PAD_ZERO;
  387. // 设置填充元素
  388. pad = (flags & PAD_ZERO) ? '0' : ' ';
  389. sign = 0;
  390. if (flags & SIGN)
  391. {
  392. int64_t signed_num = (int64_t)num;
  393. if (signed_num < 0)
  394. {
  395. sign = '-';
  396. num = -signed_num;
  397. }
  398. else
  399. num = signed_num;
  400. }
  401. else
  402. {
  403. // 设置符号
  404. sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0);
  405. }
  406. // sign占用了一个宽度
  407. if (sign)
  408. --field_width;
  409. if (flags & SPECIAL)
  410. if (base == 16) // 0x占用2个位置
  411. field_width -= 2;
  412. else if (base == 8) // O占用一个位置
  413. --field_width;
  414. int js_num = 0; // 临时数字字符串tmp_num的长度
  415. if (num == 0)
  416. tmp_num[js_num++] = '0';
  417. else
  418. {
  419. num = ABS(num);
  420. //进制转换
  421. while (num > 0)
  422. {
  423. tmp_num[js_num++] = digits[num % base]; // 注意这里,输出的数字,是小端对齐的。低位存低位
  424. num /= base;
  425. }
  426. }
  427. if (js_num > precision)
  428. precision = js_num;
  429. field_width -= precision;
  430. // 靠右对齐
  431. if (!(flags & (LEFT + PAD_ZERO)))
  432. while (field_width-- > 0)
  433. *str++ = ' ';
  434. if (sign)
  435. *str++ = sign;
  436. if (flags & SPECIAL)
  437. if (base == 16)
  438. {
  439. *str++ = '0';
  440. *str++ = digits[33];
  441. }
  442. else if (base == 8)
  443. *str++ = digits[24]; //注意这里是英文字母O或者o
  444. if (!(flags & LEFT))
  445. while (field_width-- > 0)
  446. *str++ = pad;
  447. while (js_num < precision)
  448. {
  449. --precision;
  450. *str++ = '0';
  451. }
  452. while (js_num-- > 0)
  453. *str++ = tmp_num[js_num];
  454. while (field_width-- > 0)
  455. *str++ = ' ';
  456. return str;
  457. }
  458. static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags)
  459. {
  460. /**
  461. * @brief 将浮点数按照指定的要求转换成对应的字符串
  462. *
  463. * @param str 要返回的字符串
  464. * @param num 要打印的数值
  465. * @param field_width 区域宽度
  466. * @param precision 精度
  467. * @param flags 标志位
  468. */
  469. char pad, sign, tmp_num_z[100], tmp_num_d[350];
  470. const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  471. // 显示小写字母
  472. if (flags & SMALL)
  473. digits = "0123456789abcdefghijklmnopqrstuvwxyz";
  474. // 设置填充元素
  475. pad = (flags & PAD_ZERO) ? '0' : ' ';
  476. sign = 0;
  477. if (flags & SIGN && num < 0)
  478. {
  479. sign = '-';
  480. num = -num;
  481. }
  482. else
  483. {
  484. // 设置符号
  485. sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0);
  486. }
  487. // sign占用了一个宽度
  488. if (sign)
  489. --field_width;
  490. int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度
  491. uint64_t num_z = (uint64_t)(num); // 获取整数部分
  492. uint64_t num_decimal = (uint64_t)(round(1.0*(num - num_z) * pow(10, precision))); // 获取小数部分
  493. if (num == 0 || num_z == 0)
  494. tmp_num_z[js_num_z++] = '0';
  495. else
  496. {
  497. //存储整数部分
  498. while (num_z > 0)
  499. {
  500. tmp_num_z[js_num_z++] = digits[num_z % 10]; // 注意这里,输出的数字,是小端对齐的。低位存低位
  501. num_z /= 10;
  502. }
  503. }
  504. while (num_decimal > 0)
  505. {
  506. tmp_num_d[js_num_d++] = digits[num_decimal % 10];
  507. num_decimal /= 10;
  508. }
  509. field_width -= (precision + 1 + js_num_z);
  510. // 靠右对齐
  511. if (!(flags & LEFT))
  512. while (field_width-- > 0)
  513. *str++ = pad;
  514. if (sign)
  515. *str++ = sign;
  516. // 输出整数部分
  517. // while (js_num_z-- > 0)
  518. // *str++ = tmp_num_z[js_num_z];
  519. while (js_num_z > 0)
  520. {
  521. *str++ = tmp_num_z[js_num_z - 1];
  522. --js_num_z;
  523. }
  524. *str++ = '.';
  525. // 输出小数部分
  526. int total_dec_count = js_num_d;
  527. for (int i = 0; i < precision && js_num_d-- > 0; ++i)
  528. *str++ = tmp_num_d[js_num_d];
  529. while (total_dec_count < precision)
  530. {
  531. ++total_dec_count;
  532. *str++ = '0';
  533. }
  534. while (field_width-- > 0)
  535. *str++ = ' ';
  536. return str;
  537. }
  538. static void putchar(uint *fb, int Xsize, int x, int y, unsigned int FRcolor, unsigned int BKcolor, unsigned char font)
  539. {
  540. /**
  541. * @brief 在屏幕上指定位置打印字符
  542. *
  543. * @param fb 帧缓存线性地址
  544. * @param Xsize 行分辨率
  545. * @param x 左上角列像素点位置
  546. * @param y 左上角行像素点位置
  547. * @param FRcolor 字体颜色
  548. * @param BKcolor 背景颜色
  549. * @param font 字符的bitmap
  550. */
  551. //#if DEBUG
  552. uart_send(COM1, font);
  553. //#endif
  554. unsigned char *font_ptr = font_ascii[font];
  555. unsigned int *addr;
  556. int testbit; // 用来测试某位是背景还是字体本身
  557. for (int i = 0; i < pos.char_size_y; ++i)
  558. {
  559. // 计算出帧缓冲区的地址
  560. addr = fb + Xsize * (y + i) + x;
  561. testbit = (1 << (pos.char_size_x + 1));
  562. for (int j = 0; j < pos.char_size_x; ++j)
  563. {
  564. //从左往右逐个测试相应位
  565. testbit >>= 1;
  566. if (*font_ptr & testbit)
  567. *addr = FRcolor; // 字,显示前景色
  568. else
  569. *addr = BKcolor; // 背景色
  570. ++addr;
  571. }
  572. ++font_ptr;
  573. }
  574. }
  575. /**
  576. * @brief 格式化打印字符串
  577. *
  578. * @param FRcolor 前景色
  579. * @param BKcolor 背景色
  580. * @param ... 格式化字符串
  581. */
  582. int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ...)
  583. {
  584. uint64_t rflags = 0; // 加锁后rflags存储到这里
  585. spin_lock_irqsave(&printk_lock, rflags);
  586. va_list args;
  587. va_start(args, fmt);
  588. char buf[4096]; // vsprintf()的缓冲区
  589. int len = vsprintf(buf, fmt, args);
  590. va_end(args);
  591. unsigned char current;
  592. int i; // 总共输出的字符数
  593. for (i = 0; i < len; ++i)
  594. {
  595. current = *(buf + i);
  596. //输出换行
  597. if (current == '\n')
  598. {
  599. pos.x = 0;
  600. ++pos.y;
  601. auto_newline();
  602. }
  603. else if (current == '\t') // 输出制表符
  604. {
  605. int space_to_print = 8 - pos.x % 8;
  606. while (space_to_print--)
  607. {
  608. putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, ' ');
  609. ++pos.x;
  610. auto_newline();
  611. }
  612. }
  613. else if (current == '\b') // 退格
  614. {
  615. --pos.x;
  616. if (pos.x < 0)
  617. {
  618. --pos.y;
  619. if (pos.y <= 0)
  620. pos.x = pos.y = 0;
  621. else
  622. pos.x = pos.max_x;
  623. }
  624. putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, ' ');
  625. auto_newline();
  626. }
  627. else
  628. {
  629. putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, current);
  630. ++pos.x;
  631. auto_newline();
  632. }
  633. }
  634. spin_unlock_irqrestore(&printk_lock, rflags);
  635. return i;
  636. }
  637. int do_scroll(bool direction, int pixels)
  638. {
  639. if (direction == true) // 向上滚动
  640. {
  641. pixels = pixels;
  642. if (pixels > pos.height)
  643. return EPOS_OVERFLOW;
  644. // 无需滚动
  645. if (pixels == 0)
  646. return 0;
  647. unsigned int src = pixels * pos.width;
  648. unsigned int count = pos.FB_length - src;
  649. memcpy(pos.FB_address, (pos.FB_address + src), sizeof(unsigned int) * (pos.FB_length - src));
  650. memset(pos.FB_address + (pos.FB_length - src), 0, sizeof(unsigned int) * (src));
  651. return 0;
  652. }
  653. else
  654. return EUNSUPPORTED;
  655. return 0;
  656. }
  657. /**
  658. * @brief 滚动窗口(尚不支持向下滚动)
  659. *
  660. * @param direction 方向,向上滑动为true,否则为false
  661. * @param pixels 要滑动的像素数量
  662. * @param animation 是否包含滑动动画
  663. */
  664. // @todo: 修复用户态触发键盘中断时产生#UD错误
  665. int scroll(bool direction, int pixels, bool animation)
  666. {
  667. // 暂时不支持反方向滚动
  668. if (direction == false)
  669. return EUNSUPPORTED;
  670. // 为了保证打印字符正确,需要对pixel按照字体高度对齐
  671. int md = pixels % pos.char_size_y;
  672. if (md)
  673. pixels = pixels + pos.char_size_y - md;
  674. if (animation == false)
  675. return do_scroll(direction, pixels);
  676. else
  677. {
  678. int steps;
  679. if (pixels > 10)
  680. steps = 5;
  681. else
  682. steps = pixels % 10;
  683. int half_steps = steps / 2;
  684. // 计算加速度
  685. double accelerate = 0.5 * pixels / (half_steps * half_steps);
  686. int current_pixels = 0;
  687. double delta_x;
  688. int trace[13] = {0};
  689. int js_trace = 0;
  690. // 加速阶段
  691. for (int i = 1; i <= half_steps; ++i)
  692. {
  693. trace[js_trace] = (int)(accelerate * i + 0.5);
  694. current_pixels += trace[js_trace];
  695. do_scroll(direction, trace[js_trace]);
  696. ++js_trace;
  697. }
  698. // 强制使得位置位于1/2*pixels
  699. if (current_pixels < pixels / 2)
  700. {
  701. delta_x = pixels / 2 - current_pixels;
  702. current_pixels += delta_x;
  703. do_scroll(direction, delta_x);
  704. }
  705. // 减速阶段,是加速阶段的重放
  706. for (int i = js_trace - 1; i >= 0; --i)
  707. {
  708. current_pixels += trace[i];
  709. do_scroll(direction, trace[i]);
  710. }
  711. if (current_pixels > pixels)
  712. kerror("During scrolling: scrolled pixels over bound!");
  713. // 强制使得位置位于pixels
  714. if (current_pixels < pixels)
  715. {
  716. delta_x = pixels - current_pixels;
  717. current_pixels += delta_x;
  718. do_scroll(direction, delta_x);
  719. }
  720. }
  721. return 0;
  722. }
  723. /**
  724. * @brief 清屏
  725. *
  726. */
  727. int cls()
  728. {
  729. memset(pos.FB_address, BLACK, pos.FB_length * sizeof(unsigned int));
  730. pos.x = 0;
  731. pos.y = 0;
  732. return 0;
  733. }
  734. /**
  735. * @brief 获取VBE帧缓冲区长度
  736. */
  737. ul get_VBE_FB_length()
  738. {
  739. return pos.FB_length;
  740. }
  741. /**
  742. * @brief 设置pos变量中的VBE帧缓存区的线性地址
  743. * @param virt_addr VBE帧缓存区线性地址
  744. */
  745. void set_pos_VBE_FB_addr(uint *virt_addr)
  746. {
  747. pos.FB_address = (uint *)virt_addr;
  748. }
  749. uint *get_pos_VBE_FB_addr()
  750. {
  751. return pos.FB_address;
  752. }
  753. /**
  754. * @brief 使能滚动动画
  755. *
  756. */
  757. void printk_enable_animation()
  758. {
  759. sw_show_scroll_animation = true;
  760. }
  761. /**
  762. * @brief 禁用滚动动画
  763. *
  764. */
  765. void printk_disable_animation()
  766. {
  767. sw_show_scroll_animation = false;
  768. }
  769. int sprintk(char *buf, const char *fmt, ...)
  770. {
  771. int count = 0;
  772. va_list args;
  773. va_start(args, fmt);
  774. count = vsprintf(buf, fmt, args);
  775. va_end(args);
  776. return count;
  777. }