编写设备驱动程序

附录 D 控制台帧缓存器驱动程序

用于系统控制台的帧缓存器驱动程序必须提供相应的接口,以使系统能够在控制台上显示文本。Solaris OS 可提供增强的可视化 I/O 接口,以使内核终端仿真器能够直接在控制台帧缓存器上显示文本。本附录介绍如何向帧缓存器驱动程序添加必要的接口,以使该驱动程序能够与 Solaris 内核终端仿真器进行交互。

Solaris 控制台和内核终端仿真器

内核终端仿真器的作用是按照帧缓存器的屏幕高度、宽度和像素深度模式确定的正确位置和表示法在控制台帧缓存器中呈现文本。终端仿真器还可以驱动滚动、控制软件光标,以及解释 ANSI 终端转义序列。终端仿真器以 VGA 文本模式或像素模式访问控制台帧缓存器,具体取决于图形卡。要将您的帧缓存器驱动程序用作 Solaris 控制台帧缓存器驱动程序,它必须与 Solaris 内核终端仿真器兼容。目标平台是最重要的因素,它决定了您是否需要修改帧缓存器驱动程序,以使您的驱动程序与 Solaris 内核终端仿真器兼容。

x86 平台控制台通信

在 x86 平台上,Solaris 内核终端仿真器模块 (terminal emulator module, tem) 以独占方式使用 VGA 文本模式来与 vgatext 模块进行交互。vgatext 模块使用行业标准 VGA 文本模式与 x86 兼容的帧缓存器设备进行交互。由于 vgatext 模块已经支持控制台帧缓存器接口,因此 x86 帧缓存器驱动程序与内核 tem 模块兼容。不需要向 x86 帧缓存器驱动程序添加任何特殊的接口。

本附录的其余部分仅适用于 SPARC 平台。

SPARC 平台控制台通信

SPARC 帧缓存器驱动程序通常不在 VGA 文本模式下运行。SPARC 帧缓存器驱动程序通常需要发送像素图案,以描述显示的文本和图像。内核 tem 要求 SPARC 驱动程序支持特定的接口,以便在屏幕上呈现数据、执行滚动和显示文本光标。驱动程序实际上如何在屏幕上呈现 tem 发出的数据取决于具体的设备。驱动程序通常根据硬件和视频模式在视频内存中绘制数据。

Solaris OS 提供的一些接口使内核终端仿真器能够直接驱动兼容的控制台帧缓存器。将驱动程序转换为与内核终端仿真器兼容的好处在于:

SPARC 控制台帧缓存器驱动程序不需要与内核终端仿真器兼容。如果控制台帧缓存器驱动程序不与内核终端仿真器兼容,系统将使用 OpenBoot PROM 中的 FCode 终端仿真器。

控制台帧缓存器通过 EEPROM screen 环境变量进行识别。系统通过检查帧缓存器驱动程序是否导出 tem-support DDI 属性,来确定控制台帧缓存器是否与内核终端仿真器模块兼容。如果导出了 tem-support 属性,则系统将在系统引导过程中配置控制台时对帧缓存器驱动程序发出 VIS_DEVINIT I/O 控制 (ioctl) 命令。如果导出了 tem-support DDI 属性,同时 VIS_DEVINIT ioctl 命令成功并向 tem 返回了兼容版本号,那么,系统会将系统控制台配置为通过内核终端仿真器利用该帧缓存器驱动程序。有关 I/O 控制驱动程序入口点的信息,请参见 ioctl(9E) 手册页。

支持内核终端仿真器的 SPARC 驱动程序应导出 tem-support DDI 属性。该属性表示驱动程序支持内核终端仿真器。如果帧缓存器驱动程序导出了 tem-support DDI 属性,则早在引导过程中配置控制台时就将会处理该驱动程序。如果帧缓存器驱动程序未导出 tem-support 属性,则在引导过程中,可能不会那么早就处理该驱动程序。

tem-support

设置为 1 时,此 DDI 属性表示此驱动程序与控制台内核帧缓存器接口兼容。

内核终端仿真器模块通过两种主要接口与控制台帧缓存器驱动程序进行交互:

下节将提供详细信息。

控制台可视化 I/O 接口

内核终端仿真器通过两种接口与控制台帧缓存器驱动程序进行交互。在正常的系统活动期间(系统成功引导后),内核终端仿真器与控制台帧缓存器驱动程序之间的通信通过 ioctl 接口进行。在独立模式期间(系统引导之前或调试期间),内核终端仿真器与控制台帧缓存器驱动程序之间的通信通过轮询式 I/O 接口进行。内核终端仿真器与控制台帧缓存器驱动程序之间的所有活动都由内核终端仿真器启动,但控制台帧缓存器驱动程序用来通知内核终端仿真器有关视频模式方面的变化的回调函数除外。

visual_io(7I) 手册页中详细说明了控制台可视化 I/O 接口。有关视频模式更改回调函数的更多信息,请参见视频模式更改回调接口

I/O 控制接口

在正常的系统活动期间,内核终端仿真器通过下表中列出的 ioctl 接口与控制台帧缓存器驱动程序进行通信:

ioctl 名称

对应的数据结构 

说明 

VIS_DEVINIT

vis_devinit

初始化终端仿真器模块与帧缓存器之间的会话。请参见VIS_DEVINIT

VIS_DEVFINI

不适用 

终止终端仿真器模块与帧缓存器之间的会话。请参见VIS_DEFINI

VIS_CONSDISPLAY

vis_consdisplay

以矩形显示像素。请参见VIS_CONSDISPLAY

VIS_CONSCOPY

vis_conscopy

复制像素的矩形区(滚动)。请参见VIS_CONSCOPY

VIS_CONSCURSOR

vis_conscursor

显示或隐藏文本光标。请参见VIS_CONSCURSOR

VIS_PUTCMAP

vis_cmap

将终端仿真器模块色彩表发送到帧缓存器驱动程序。请参见VIS_PUTCMAP

VIS_GETCMAP

vis_cmap

从帧缓存器读取终端仿真器模块色彩表。请参见VIS_GETCMAP

轮询式 I/O 接口

轮询式 I/O 接口提供的功能与 VIS_CONSDISPLAYVIS_CONSCOPY VIS_CONSCURSOR ioctl 接口的功能相同。仅当操作系统处于静止状态并处于独立模式时,才调用轮询式 I/O 接口。有关更多信息,请参见在控制台帧缓存器驱动程序中实现轮询式 I/O

处于独立模式时,内核终端仿真器通过下表中列出的轮询式 I/O 接口与控制台帧缓存器驱动程序进行通信:

轮询式 I/O 函数 

对应的数据结构 

说明 

(*display)()

vis_consdisplay

以矩形显示像素。 

(*copy)()

vis_conscopy

复制像素的矩形区(滚动)。 

(*cursor)()

vis_conscursor

显示或隐藏文本光标。 

视频模式更改回调接口

在任何时候,控制台帧缓存器驱动程序与内核终端仿真器都必须就视频模式取得一致。视频模式涉及到控制台屏幕高度、宽度和深度(以像素为单位)。视频模式还涉及到内核终端仿真器与控制台帧缓存器之间的通信是在 VGA 文本模式还是在像素模式下进行。

为了让控制台帧缓存器驱动程序通知内核终端仿真器有关视频模式方面的变化,将使用下表中所述的 (*modechg_cb)() 内核终端仿真器回调函数的地址初始化控制台帧缓存器驱动程序:

回调函数 

对应的数据结构 

说明 

(*modechg_cb)()

vis_modechg_arg

vis_devinit

使终端仿真器模块与驱动程序视频模式(屏幕高度、宽度和像素深度)保持同步。 

在控制台帧缓存器驱动程序中实现可视化 I/O 接口

除了视频模式更改回调外,驱动程序与内核终端仿真器之间的所有活动都由 tem(terminal emulator module,终端仿真器模块)启动。这意味着,tem 将发出本文档中介绍的所有 ioctl 命令。以下各节提供了有关每个 ioctl 命令的实现详细信息。有关更多信息,请参见 visual_io(7I) 手册页和 /usr/include/sys/visual_io.h 头文件。有关视频模式更改回调函数的详细信息,请参见视频模式更改回调接口


注 –

每个 ioctl 命令都应确定是否已在 ioctl 标志参数中设置 FKIOCTL,如果未设置该位,则返回 EPERM


VIS_DEVINIT

VIS_DEVINIT ioctl 命令将帧缓存器驱动程序初始化为系统控制台设备。该 ioctl 将传递 vis_devinit 结构的地址。

tem 首先将其视频模式更改回调函数的地址装入 vis_devinit 结构的 modechg_cb 字段,再将其软状态装入 modechg_arg 字段。然后,tem 发出 VIS_DEVINIT ioctl 命令。接下来,帧缓存器驱动程序初始化自身,并通过设置 vis_devinit 结构中的 version widthheightlinebytesdepthmodepolledio 字段将自身的配置摘要返回到 tem。以下代码中显示了 vis_devinit 结构。

struct vis_devinit {
      /*
       * This set of fields are used as parameters passed from the
       * layered frame buffer driver to the terminal emulator.
       */
      int             version;        /* Console IO interface rev */
      screen_size_t   width;          /* Width of the device */
      screen_size_t   height;         /* Height of the device */
      screen_size_t   linebytes;      /* Bytes per scan line */
      int             depth;          /* Device depth */
      short           mode;           /* Display mode Mode */
      struct vis_polledio *polledio;  /* Polled output routines */
      /*
       * The following fields are used as parameters passed from the
       * terminal emulator to the underlying frame buffer driver.
       */
      vis_modechg_cb_t modechg_cb;   /* Video mode change callback */
      struct vis_modechg_arg *modechg_arg;  /* Mode change cb arg */
};

要在控制台帧缓存器驱动程序中实现 VIS_DEVINIT ioctl 命令,请按照以下通用步骤操作:

  1. 定义一个 struct 以包含特定于控制台的状态。该结构由控制台帧缓存器驱动程序专用。在本附录中,该结构称为 consinfoconsinfo 结构包含诸如以下的信息:

    • 位块传输 (blit) 缓冲区的当前大小

    • 指向位块传输 (blit) 缓冲区的指针

    • 色彩表信息

    • 呈现模式信息(如行间距)的驱动程序

    • 背景色

    • 视频内存地址

    • 终端仿真器回调地址

  2. 分配内存:

    1. 分配足够大的位块传输 (blit) 缓冲区,以便以最高的视频深度存储像素的合理的、缺省大小的矩形区。如果传入的请求超出缓冲区的大小,可以分配额外的内存。帧缓存器驱动程序的最大字体大小为 12×22。假设 DEFAULT_HEIGHT 为 12,DEFAULT_WIDTH 为 22,最大视频深度为 32,那么,缓冲区大小应为 8448 个字节 (DEFAULT_HEIGHT × DEFAULT_WIDTH × 32)。

    2. 分配 vis_polledio 结构。

    3. 分配缓冲区以用于保持光标。该缓冲区的大小应相当于最大字符的大小。该缓冲区的大小将不会发生变化。

  3. modechg_cbmodechg_ctx 获取 tem 的视频更改回调地址和回调上下文,并将这些信息存储在 consinfo 结构中。

  4. 使用轮询式显示、副本和光标函数的入口点地址填充 vis_polledio 结构。

  5. tem 传递给驱动程序的 vis_devinit 结构的字段中提供相应信息:

    1. version 字段设置为 VIS_CONS_REV,这是 /usr/include/sys/visual_io.h 头文件中定义的一个常量。

    2. mode 字段设置为 VIS_PIXEL

    3. polledio 字段设置为 vis_polledio 结构的地址。

    4. height 字段设置为视频模式高度(以像素为单位)。

    5. width 字段设置为视频模式宽度(以像素为单位)。

    6. depth 字段设置为帧缓存器像素深度,单位为字节(例如,32 位像素深度将为 4 个字节)。

    7. linebytes 字段设置为 height × width × depth 的值。

      将会使用 vis_devinit 结构将这些信息从驱动程序发送到 tem。通过这些信息,终端仿真器可知道如何呈现信息以及如何将信息传递给图形驱动程序。

    每当控制台帧缓存器驱动程序更改视频模式(具体而言,heightwidthdepth)时,它都必须调用 tem 的视频模式更改回调函数,以更新 vis_devinit 结构,并将此结构传递回给终端仿真器。终端仿真器将其模式更改回调函数地址传入 vis_devinit 结构的 modechg_cb 字段。模式更改回调函数具有以下函数签名:

    typedef void (*vis_modechg_cb_t)
          (struct vis_modechg_arg *, struct vis_devinit *);

    如前面的 typedef 中所述,模式更改回调函数使用两个参数。第一个参数为 modechg_arg,第二个参数为 vis_devinit 结构。modechg_arg 会在 VIS_DEVINIT ioctl 命令初始化期间从 tem 发送到驱动程序。驱动程序必须通过每个视频模式更改回调将 modechg_arg 发送回给 tem

  6. 初始化内核控制台的上下文。具体的要求会随图形设备的功能而异。例如,该初始化的步骤可能包括:设置绘制引擎状态、初始化调色板,或者定位和映射视频内存或呈现引擎,以便数据能够以位块传输到屏幕。

  7. vis_devinit 结构返回给调用方。

VIS_DEFINI

VIS_DEFINI ioctl 命令可释放驱动程序的控制台资源,并完成会话。

要在控制台帧缓存器驱动程序中实现 VIS_DEVFINI ioctl 命令,请按照以下通用步骤操作:

  1. 重置控制台帧缓存器驱动程序状态。

  2. 清除轮询式 I/O 入口点和内核终端仿真器视频更改函数回调地址。

  3. 释放内存。

VIS_CONSDISPLAY

VIS_CONSDISPLAY ioctl 命令可在指定的位置显示像素矩形区。这种显示方式又称为以位块传输 (blitting) 矩形。vis_consdisplay 结构包含以驱动程序和 tem 使用的视频深度呈现矩形所必需的信息。以下代码中显示了 vis_consdisplay 结构。

struct vis_consdisplay {
      screen_pos_t    row;      /* Row (in pixels) to display data at */
      screen_pos_t    col;      /* Col (in pixels) to display data at */
      screen_size_t   width;    /* Width of data (in pixels) */
      screen_size_t   height;   /* Height of data (in pixels) */
      unsigned char   *data;    /* Address of pixels to display */
      unsigned char   fg_color; /* Foreground color */
      unsigned char   bg_color; /* Background color */
};

要在控制台帧缓存器驱动程序中实现 VIS_CONSDISPLAY ioctl 命令,请按照以下通用步骤操作:

  1. 复制 vis_consdisplay 结构。

  2. 验证显示参数。如果任一显示参数超出范围,则会返回错误。

  3. 计算要以位块传输到视频内存的矩形的大小。根据执行 VIS_DEVINIT 期间创建的位块传输 (blit) 缓冲区大小验证此大小。如果需要,为位块传输 (blit) 缓冲区分配额外的内存。

  4. 检索位块传输 (blit) 数据。内核终端仿真器已在议定的像素深度准备了此数据。该深度与执行 VIS_DEVINIT 期间 tem 传递的像素深度相同。每当设备驱动程序通过 tem 的回调更改视频模式时,都会更新像素深度。典型的像素深度为 8 位索引色彩表和 32 位真彩 (TrueColor)。

  5. 使所有用户上下文无效,以使用户应用程序不能通过用户内存映射同时访问帧缓存器硬件。在轮询式 I/O 模式下,既不允许也没有必要执行此步骤,因为用户应用程序并没有运行。请务必持有锁,以便在完成 VIS_CONSDISPLAY ioctl 之前,用户无法通过缺页恢复映射。

  6. 建立特定于驱动程序的控制台呈现上下文。

  7. 如果帧缓存器在 8 位索引色彩模式下运行,请恢复 tem 以前通过 VIS_PUTCMAP ioctl 设置的内核控制台色彩表。建议使用延迟 ( lazy) 色彩表装入方案,以优化性能。在延迟 (lazy) 方案中,控制台帧缓存器只恢复自发出 VIS_DEVINIT ioctl 以来实际使用的色彩。

  8. tem 发送的像素坐标上显示 tem 传出的数据。您可能需要转换 RGB 像素数据字节顺序。

VIS_CONSCOPY

VIS_CONSCOPY ioctl 命令可将像素矩形区从一个位置复制到另一个位置。该 ioctl 的用途之一就是执行滚动。

要在控制台帧缓存器驱动程序中实现 VIS_CONSCOPY ioctl 命令,请按照下面的通用步骤操作:

  1. 复制 vis_conscopy 结构。vis_conscopy 结构描述源和目标矩形大小与位置。

  2. 验证显示参数。如果任一显示参数超出范围,则会返回错误。

  3. 使所有用户上下文无效,以使用户应用程序不能通过用户内存映射同时访问帧缓存器硬件。在轮询式 I/O 模式下,既不允许也没有必要执行此步骤,因为用户应用程序并没有运行。请务必持有锁,以便在完成 VIS_CONSDISPLAY ioctl 之前,用户无法通过缺页恢复映射。

  4. 调用函数以复制矩形。


    注 –

    为实现最佳性能,请使用图形设备的呈现引擎来实现复制功能。您需要确定如何执行驱动程序内的上下文管理以设置呈现引擎,从而实现最佳性能。


VIS_CONSCURSOR

VIS_CONSCURSOR ioctl 命令可显示或隐藏光标。以下代码中显示了 vis_conscursor 结构。

struct vis_conscursor {
      screen_pos_t    row;      /* Row to display cursor (in pixels) */
      screen_pos_t    col;      /* Col to display cursor (in pixels) */
      screen_size_t   width;    /* Width of cursor (in pixels) */
      screen_size_t   height;   /* Height of cursor (in pixels) */
      color_t         fg_color; /* Foreground color */
      color_t         bg_color; /* Background color */
      short           action;   /* Show or Hide cursor */
};

要在控制台帧缓存器驱动程序中实现 VIS_CONSCOPY ioctl 命令,请按照下面的通用步骤操作:

  1. 从内核终端仿真器复制 vis_conscursor 结构。

  2. 验证显示参数。如果任一显示参数超出范围,则会返回错误。

  3. 使所有用户上下文无效,以使用户应用程序不能通过用户内存映射同时访问帧缓存器硬件。在轮询式 I/O 模式下,既不允许也没有必要执行此步骤,因为用户应用程序并没有运行。请务必持有锁,以便在完成 VIS_CONSDISPLAY ioctl 之前,用户无法通过缺页恢复映射。

  4. 终端仿真器可通过以下两个操作之一调用 VIS_CONSCOPY ioctlSHOW_CURSORHIDE_CURSOR。以下步骤介绍如何通过读取和写入视频内存实现此功能。您可能也可使用呈现引擎来完成此工作。是否能够使用呈现引擎取决于帧缓存器硬件。

    执行以下步骤可实现 SHOW_CURSOR 功能:

    1. 将像素保存到要在其中绘制光标的矩形内。隐藏光标时将需要使用这些保存的像素。

    2. 扫描要在其中绘制光标的矩形界定的屏幕上的所有像素。在此矩形中,将与指定光标前景色 (fg_color) 匹配的像素替换为白色像素。将与指定光标背景色 (bg_color) 匹配的像素替换为黑色像素。视觉效果为黑色光标悬停在白色文本上。此方法适用于文本的任何前景色和背景色。尝试根据色彩表位置进行反色是不切实际的。也没有必要使用更复杂的策略,例如使用 HSB(Hue, Saturation, Brightness,色调、饱和度和亮度)色彩模式进行反色。

    要实现 HIDE_CURSOR 功能,请将光标矩形下方的像素替换为通过前面的 SHOW_CURSOR 操作保存的像素。

VIS_PUTCMAP

VIS_PUTCMAP ioctl 命令可建立控制台色彩表。终端仿真器调用此函数以设置内核的色彩表。以下代码中显示了 vis_cmap 结构。该结构只适用于 8 位索引色彩模式。

struct vis_cmap {
      int             index;  /* Index into colormap to start updating */
      int             count;  /* Number of entries to update */
      unsigned char   *red;   /* List of red values */
      unsigned char   *green; /* List of green values */
      unsigned char   *blue;  /* List of blue values */
};

VIS_PUTCMAP ioctl 命令与 FBIOPUTCMAP 命令类似。VIS_PUTCMAP 命令特定于与帧缓存器终端仿真器兼容的控制台代码。

VIS_GETCMAP

终端仿真器可调用 VIS_GETCMAP ioctl 命令来检索控制台色彩表。

在控制台帧缓存器驱动程序中实现轮询式 I/O

轮询式 I/O 接口在驱动程序中作为函数实现,并由内核终端仿真器直接调用。在执行 VIS_DEVINIT ioctl 命令期间,驱动程序会将其轮询式 I/O 入口点的地址传递给终端仿真器。VIS_DEVINIT 命令由终端仿真器启动。

以下代码中显示了 vis_polledio 结构。

typedef void * vis_opaque_arg_t;

struct vis_polledio {
      struct vis_polledio_arg *arg;
      void    (*display)(vis_opaque_arg_t, struct vis_consdisplay *);
      void    (*copy)(vis_opaque_arg_t, struct vis_conscopy *);
      void    (*cursor)(vis_opaque_arg_t, struct vis_conscursor *);
};

轮询式 I/O 接口提供的功能与 VIS_CONSDISPLAYVIS_CONSCOPY VIS_CONSCURSOR ioctl 接口的功能相同。要实现轮询式 I/O 接口,应该按照上面针对相应 ioctl 命令所述的相同步骤操作。轮询式 I/O 接口必须严格遵循本节其余部分所述的其他限制。

仅当操作系统处于静止状态并处于独立模式时,才调用轮询式 I/O 接口。每当用户进入 OpenBoot PROM 或 kmdb 调试器时,或者系统出现紧急情况时,系统就会进入独立模式。此时,只有一个 CPU 和一个线程处于活动状态。其他所有 CPU 和线程均会停止。分时、DDI 中断和系统服务都将关闭。

独立模式会严重限制驱动程序的功能,但会简化驱动程序同步要求。例如,用户应用程序无法通过在轮询式 I/O 例程中对控制台帧缓存器驱动程序进行内存映射这样的方式来访问该驱动程序。

在独立模式下,控制台帧缓存器驱动程序不得执行下列任一操作:

遵守这些限制并不困难,因为操作轮询式 I/O 函数相对较为简单。例如,在使用呈现引擎时,控制台帧缓存器驱动程序可以轮询设备中的某个位,而不是等待中断。驱动程序可以使用预先分配的内存来呈现位块传输 (blit) 数据。DDI 或 LDI 接口应该是不需要的。

特定于帧缓存器的配置模块

当特定于驱动程序的 fbconfig() 模块导致分辨率或颜色深度发生变化时,该 fbconfig() 模块必须向帧缓存器驱动程序发送 ioctl。此 ioctl 将触发帧缓存器驱动程序,使其使用新的屏幕大小和深度调用终端仿真器的模式更改回调函数。在任何时候,帧缓存器驱动程序与终端仿真器必须就视频模式取得一致。如果帧缓存器驱动程序与终端仿真器未就视频模式取得一致,屏幕上的信息将难以辩认,从而没有意义。

特定于 X 窗口系统帧缓存器的 DDX 模块

当 X 窗口系统退出命令行时,帧缓存器的 DDX 模块必须向帧缓存器驱动程序发送 ioctl。此 ioctl 将触发帧缓存器驱动程序,使其调用终端仿真器的模式更改回调函数。如果 X 窗口系统在启动之后,退出之前更改了视频分辨率,这种通信将使帧缓存器驱动程序与终端仿真器就视频模式取得一致。在任何时候,帧缓存器驱动程序与终端仿真器必须就视频模式取得一致。如果帧缓存器驱动程序与终端仿真器未就视频模式取得一致,屏幕上的信息将难以辩认,从而没有意义。

开发、测试和调试控制台帧缓存器驱动程序

在活动的系统上调试控制台帧缓存器驱动程序可能会遇到问题。

本节提供了一些建议,可帮助您开发、测试和调试控制台帧缓存器驱动程序。

测试 I/O 控制接口

要测试 ioctl 命令,请额外创建一些可通过用户应用程序调用的 ioctl 入口点。确保正确地复制参数。使用 ddi_copyin(9F)ddi_copyout(9F) 例程在用户地址空间来回传输数据。然后编写一个应用程序,以验证呈现、滚动和光标行为。这样,在您开发和测试这些 ioctl 命令时,它们就不会影响您的控制台。

为确保 ioctl 命令正常工作,请引导系统,然后登录。检查在执行 prstat(1M)、ls(1)、 vi(1) 和 man(1) 等命令时,是否能够得到预期的行为。

执行以下脚本以验证 ANSI 颜色是否正常工作:

#!/bin/bash
printf "\n\n\n\e[37;40m             Color List       \e[m\n\n"
printf "\e[30m Color 30 black\e[m\n"
printf "\e[31m Color 31 red\e[m\n"
printf "\e[32m Color 32 green\e[m\n"
printf "\e[33m Color 33 yellow\e[m\n"
printf "\e[34m Color 34 blue\e[m\n"
printf "\e[35m Color 35 purple\e[m\n"
printf "\e[36m Color 36 cyan\e[m\n"
printf "\e[37m Color 37 white\e[m\n\n"
printf "\e[40m Backlight 40 black \e[m\n"
printf "\e[41m Backlight 41 red   \e[m\n"
printf "\e[34;42m Backlight 42 green \e[m\n"
printf "\e[43m Backlight 43 yellow\e[m\n"
printf "\e[37;44m Backlight 44 blue  \e[m\n"
printf "\e[45m Backlight 45 purple\e[m\n"
printf "\e[30;46m Backlight 46 cyan  \e[m\n"
printf "\e[30;47m Backlight 47 white \e[m\n\n"

测试轮询式 I/O 接口

轮询式 I/O 接口仅在以下情况下可用:

轮询式 I/O 接口仅在引导过程的特定点可用。运行系统之前从 OpenBoot PROM 发出的轮询式 I/O 请求不会呈现。同样,配置控制台之前发出的 kmdb 提示也不会呈现。

要测试轮询式 I/O 接口,请使用 L1+A 击键序列进入 OpenBoot PROM。要验证是否正在使用轮询式 I/O 接口,请在 OpenBoot PROM ok 提示符下键入以下命令:


ok 1b emit ." [32m This is a test" 1b emit ." [m"

如果以下叙述属实,则表明轮询式 I/O 接口工作正常:

测试视频模式更改回调函数

要确定视频模式更改回调函数是否正常工作,请登录系统,然后使用 fbconfig(1M) 多次更改帧缓存器的分辨率和深度。如果控制台能够继续正常显示文本,则表明视频模式更改回调函数工作正常。内核终端仿真器可能会调整字体大小以适合不同的屏幕大小,但这并不会对控制台帧缓存器驱动程序有重大影响。

要确定 X 窗口系统和控制台帧缓存器驱动程序是否正常交互,请在 X 窗口系统与命令行之间进行多次切换,同时,以不同的方式修改 X 窗口系统的视频分辨率和命令行分辨率。如果 X 窗口系统退出,并且控制台字符不能正常显示,则要么是 X 窗口系统未将视频模式已更改的情况通知给驱动程序控制台代码,要么是驱动程序未调用内核终端仿真器的视频模式更改回调函数。

有关测试控制台帧缓存器驱动程序的其他建议

在引导过程中,如果系统找不到或者无法成功装入与内核终端仿真器兼容的帧缓存器驱动程序,系统将向 /var/adm/messages 发送消息。要监视这些消息,请在单独的窗口中键入以下命令:


% tail -f /var/adm/messages

为避免调试驱动程序时 USB 发生问题,请更改 EEPROM input-device NVRAM 配置参数,以使用串行端口来代替键盘。有关此参数的更多信息,请参见 eeprom(1M) 手册页。