Writing Device Drivers


The VIS_DEVINIT ioctl command initializes the frame buffer driver as the system console device. This ioctl passes the address of a vis_devinit structure.

The tem first loads the address of its video mode change callback function into the modechg_cb field of the vis_devinit structure and loads its soft state into the modechg_arg field. The tem then issues the VIS_DEVINIT ioctl command. The frame buffer driver then initializes itself and returns a summary of its configuration back to the tem by setting the version, width, height, linebytes, depth, mode, and polledio fields in the vis_devinit structure. The vis_devinit structure is shown in the following code.

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 */

To implement the VIS_DEVINIT ioctl command in the console frame buffer driver, follow these general steps:

  1. Define a struct to contain the console-specific state. This structure is private to the console frame buffer driver. This structure is referred to as consinfo in this appendix. The consinfo structure contains information such as:

    • Current size of the blit buffer

    • Pointer to the blit buffer

    • Color map information

    • Driver rendering mode information such as line pitch

    • Background color

    • Video memory address

    • Terminal emulator callback address

  2. Allocate memory:

    1. Allocate a blit buffer large enough to store a reasonable default sized rectangle of pixels at the highest video depth. Additional memory can be allocated if an incoming request exceeds the size of the buffer. The frame buffer driver's largest font is 12×22. Assuming DEFAULT_HEIGHT is 12, DEFAULT_WIDTH is 22, and the maximum video depth is 32, the buffer size should be 8448 bytes (DEFAULT_HEIGHT × DEFAULT_WIDTH × 32).

    2. Allocate a vis_polledio structure.

    3. Allocate a buffer to hold a cursor. This buffer should be the size of the largest character. This buffer will not change size.

  3. Obtain the video change callback address and callback context of the tem from modechg_cb and modechg_ctx and store this information in the consinfo structure.

  4. Populate the vis_polledio structure with entry point addresses for the polled display, copy, and cursor functions.

  5. Provide the appropriate information in the fields of the vis_devinit structure that was passed to the driver by the tem:

    1. Set the version field to VIS_CONS_REV, which is a constant defined in the /usr/include/sys/visual_io.h header file.

    2. Set the mode field to VIS_PIXEL.

    3. Set the polledio field to the address of the vis_polledio structure.

    4. Set the height field to the video mode height in pixels.

    5. Set the width field to the video mode width in pixels.

    6. Set the depth field to the frame buffer pixel depth in bytes (for example, a 32-bit pixel depth would be 4 bytes).

    7. Set the linebytes field to the value of height × width × depth.

      This information is sent from the driver to the tem by using the vis_devinit structure. This information tells the terminal emulator how to render information and pass it to the graphics driver.

    Whenever the console frame buffer driver changes its video mode (specifically height, width, or depth), the driver must call the video mode change callback function of the tem to update the vis_devinit structure and to pass this structure back to the terminal emulator. The terminal emulator passes its mode change callback function address in the modechg_cb field of the vis_devinit structure. The mode change callback function has the following function signature:

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

    As shown in the preceding typedef, the mode change callback function takes two arguments. The first argument is the modechg_arg and the second argument is the vis_devinit structure. The modechg_arg is sent from the tem to the driver during the VIS_DEVINIT ioctl command initialization. The driver must send the modechg_arg back to the tem with each video mode change callback.

  6. Initialize the context of the kernel console. Specific requirements vary depending upon the capability of the graphics device. This initialization might include such steps as setting the draw engine state, initializing the palette, or locating and mapping video memory or the rendering engine so that data can be blitted onto the screen.

  7. Return the vis_devinit structure to the caller.