122944501Smrg/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*- 222944501Smrg * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com 322944501Smrg * 422944501Smrg * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 522944501Smrg * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 622944501Smrg * All rights reserved. 722944501Smrg * 822944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a 922944501Smrg * copy of this software and associated documentation files (the "Software"), 1022944501Smrg * to deal in the Software without restriction, including without limitation 1122944501Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1222944501Smrg * and/or sell copies of the Software, and to permit persons to whom the 1322944501Smrg * Software is furnished to do so, subject to the following conditions: 1422944501Smrg * 1522944501Smrg * The above copyright notice and this permission notice (including the next 1622944501Smrg * paragraph) shall be included in all copies or substantial portions of the 1722944501Smrg * Software. 1822944501Smrg * 1922944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2022944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2122944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2222944501Smrg * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2322944501Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2422944501Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2522944501Smrg * OTHER DEALINGS IN THE SOFTWARE. 2622944501Smrg * 2722944501Smrg * Authors: 2822944501Smrg * Jeff Hartmann <jhartmann@valinux.com> 2922944501Smrg * Keith Whitwell <keith@tungstengraphics.com> 3022944501Smrg * 3122944501Smrg * Rewritten by: 3222944501Smrg * Gareth Hughes <gareth@valinux.com> 3322944501Smrg */ 3422944501Smrg 3522944501Smrg#ifndef __MGA_DRM_H__ 3622944501Smrg#define __MGA_DRM_H__ 3722944501Smrg 3822944501Smrg#include "drm.h" 3922944501Smrg 4000a23bdaSmrg#if defined(__cplusplus) 4100a23bdaSmrgextern "C" { 4200a23bdaSmrg#endif 4300a23bdaSmrg 4422944501Smrg/* WARNING: If you change any of these defines, make sure to change the 4522944501Smrg * defines in the Xserver file (mga_sarea.h) 4622944501Smrg */ 4722944501Smrg 4822944501Smrg#ifndef __MGA_SAREA_DEFINES__ 4922944501Smrg#define __MGA_SAREA_DEFINES__ 5022944501Smrg 5122944501Smrg/* WARP pipe flags 5222944501Smrg */ 5322944501Smrg#define MGA_F 0x1 /* fog */ 5422944501Smrg#define MGA_A 0x2 /* alpha */ 5522944501Smrg#define MGA_S 0x4 /* specular */ 5622944501Smrg#define MGA_T2 0x8 /* multitexture */ 5722944501Smrg 5822944501Smrg#define MGA_WARP_TGZ 0 5922944501Smrg#define MGA_WARP_TGZF (MGA_F) 6022944501Smrg#define MGA_WARP_TGZA (MGA_A) 6122944501Smrg#define MGA_WARP_TGZAF (MGA_F|MGA_A) 6222944501Smrg#define MGA_WARP_TGZS (MGA_S) 6322944501Smrg#define MGA_WARP_TGZSF (MGA_S|MGA_F) 6422944501Smrg#define MGA_WARP_TGZSA (MGA_S|MGA_A) 6522944501Smrg#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) 6622944501Smrg#define MGA_WARP_T2GZ (MGA_T2) 6722944501Smrg#define MGA_WARP_T2GZF (MGA_T2|MGA_F) 6822944501Smrg#define MGA_WARP_T2GZA (MGA_T2|MGA_A) 6922944501Smrg#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) 7022944501Smrg#define MGA_WARP_T2GZS (MGA_T2|MGA_S) 7122944501Smrg#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) 7222944501Smrg#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) 7322944501Smrg#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) 7422944501Smrg 7522944501Smrg#define MGA_MAX_G200_PIPES 8 /* no multitex */ 7622944501Smrg#define MGA_MAX_G400_PIPES 16 7722944501Smrg#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES 7822944501Smrg#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */ 7922944501Smrg 8022944501Smrg#define MGA_CARD_TYPE_G200 1 8122944501Smrg#define MGA_CARD_TYPE_G400 2 8222944501Smrg#define MGA_CARD_TYPE_G450 3 /* not currently used */ 8322944501Smrg#define MGA_CARD_TYPE_G550 4 8422944501Smrg 8522944501Smrg#define MGA_FRONT 0x1 8622944501Smrg#define MGA_BACK 0x2 8722944501Smrg#define MGA_DEPTH 0x4 8822944501Smrg 8922944501Smrg/* What needs to be changed for the current vertex dma buffer? 9022944501Smrg */ 9122944501Smrg#define MGA_UPLOAD_CONTEXT 0x1 9222944501Smrg#define MGA_UPLOAD_TEX0 0x2 9322944501Smrg#define MGA_UPLOAD_TEX1 0x4 9422944501Smrg#define MGA_UPLOAD_PIPE 0x8 9522944501Smrg#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ 9622944501Smrg#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ 9722944501Smrg#define MGA_UPLOAD_2D 0x40 9822944501Smrg#define MGA_WAIT_AGE 0x80 /* handled client-side */ 9922944501Smrg#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ 10022944501Smrg#if 0 10122944501Smrg#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock 10222944501Smrg quiescent */ 10322944501Smrg#endif 10422944501Smrg 10522944501Smrg/* 32 buffers of 64k each, total 2 meg. 10622944501Smrg */ 10722944501Smrg#define MGA_BUFFER_SIZE (1 << 16) 10822944501Smrg#define MGA_NUM_BUFFERS 128 10922944501Smrg 11022944501Smrg/* Keep these small for testing. 11122944501Smrg */ 11222944501Smrg#define MGA_NR_SAREA_CLIPRECTS 8 11322944501Smrg 11400a23bdaSmrg/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 11522944501Smrg * regions, subject to a minimum region size of (1<<16) == 64k. 11622944501Smrg * 11722944501Smrg * Clients may subdivide regions internally, but when sharing between 11822944501Smrg * clients, the region size is the minimum granularity. 11922944501Smrg */ 12022944501Smrg 12122944501Smrg#define MGA_CARD_HEAP 0 12222944501Smrg#define MGA_AGP_HEAP 1 12322944501Smrg#define MGA_NR_TEX_HEAPS 2 12422944501Smrg#define MGA_NR_TEX_REGIONS 16 12522944501Smrg#define MGA_LOG_MIN_TEX_REGION_SIZE 16 12622944501Smrg 12722944501Smrg#define DRM_MGA_IDLE_RETRY 2048 12822944501Smrg 12922944501Smrg#endif /* __MGA_SAREA_DEFINES__ */ 13022944501Smrg 13122944501Smrg/* Setup registers for 3D context 13222944501Smrg */ 13322944501Smrgtypedef struct { 13422944501Smrg unsigned int dstorg; 13522944501Smrg unsigned int maccess; 13622944501Smrg unsigned int plnwt; 13722944501Smrg unsigned int dwgctl; 13822944501Smrg unsigned int alphactrl; 13922944501Smrg unsigned int fogcolor; 14022944501Smrg unsigned int wflag; 14122944501Smrg unsigned int tdualstage0; 14222944501Smrg unsigned int tdualstage1; 14322944501Smrg unsigned int fcol; 14422944501Smrg unsigned int stencil; 14522944501Smrg unsigned int stencilctl; 14622944501Smrg} drm_mga_context_regs_t; 14722944501Smrg 14822944501Smrg/* Setup registers for 2D, X server 14922944501Smrg */ 15022944501Smrgtypedef struct { 15122944501Smrg unsigned int pitch; 15222944501Smrg} drm_mga_server_regs_t; 15322944501Smrg 15422944501Smrg/* Setup registers for each texture unit 15522944501Smrg */ 15622944501Smrgtypedef struct { 15722944501Smrg unsigned int texctl; 15822944501Smrg unsigned int texctl2; 15922944501Smrg unsigned int texfilter; 16022944501Smrg unsigned int texbordercol; 16122944501Smrg unsigned int texorg; 16222944501Smrg unsigned int texwidth; 16322944501Smrg unsigned int texheight; 16422944501Smrg unsigned int texorg1; 16522944501Smrg unsigned int texorg2; 16622944501Smrg unsigned int texorg3; 16722944501Smrg unsigned int texorg4; 16822944501Smrg} drm_mga_texture_regs_t; 16922944501Smrg 17022944501Smrg/* General aging mechanism 17122944501Smrg */ 17222944501Smrgtypedef struct { 17322944501Smrg unsigned int head; /* Position of head pointer */ 17422944501Smrg unsigned int wrap; /* Primary DMA wrap count */ 17522944501Smrg} drm_mga_age_t; 17622944501Smrg 17722944501Smrgtypedef struct _drm_mga_sarea { 17822944501Smrg /* The channel for communication of state information to the kernel 17922944501Smrg * on firing a vertex dma buffer. 18022944501Smrg */ 18122944501Smrg drm_mga_context_regs_t context_state; 18222944501Smrg drm_mga_server_regs_t server_state; 18322944501Smrg drm_mga_texture_regs_t tex_state[2]; 18422944501Smrg unsigned int warp_pipe; 18522944501Smrg unsigned int dirty; 18622944501Smrg unsigned int vertsize; 18722944501Smrg 18822944501Smrg /* The current cliprects, or a subset thereof. 18922944501Smrg */ 19022944501Smrg struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS]; 19122944501Smrg unsigned int nbox; 19222944501Smrg 19322944501Smrg /* Information about the most recently used 3d drawable. The 19422944501Smrg * client fills in the req_* fields, the server fills in the 19522944501Smrg * exported_ fields and puts the cliprects into boxes, above. 19622944501Smrg * 19722944501Smrg * The client clears the exported_drawable field before 19822944501Smrg * clobbering the boxes data. 19922944501Smrg */ 20022944501Smrg unsigned int req_drawable; /* the X drawable id */ 20122944501Smrg unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ 20222944501Smrg 20322944501Smrg unsigned int exported_drawable; 20422944501Smrg unsigned int exported_index; 20522944501Smrg unsigned int exported_stamp; 20622944501Smrg unsigned int exported_buffers; 20722944501Smrg unsigned int exported_nfront; 20822944501Smrg unsigned int exported_nback; 20922944501Smrg int exported_back_x, exported_front_x, exported_w; 21022944501Smrg int exported_back_y, exported_front_y, exported_h; 21122944501Smrg struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS]; 21222944501Smrg 21322944501Smrg /* Counters for aging textures and for client-side throttling. 21422944501Smrg */ 21522944501Smrg unsigned int status[4]; 21622944501Smrg unsigned int last_wrap; 21722944501Smrg 21822944501Smrg drm_mga_age_t last_frame; 21922944501Smrg unsigned int last_enqueue; /* last time a buffer was enqueued */ 22022944501Smrg unsigned int last_dispatch; /* age of the most recently dispatched buffer */ 22122944501Smrg unsigned int last_quiescent; /* */ 22222944501Smrg 22322944501Smrg /* LRU lists for texture memory in agp space and on the card. 22422944501Smrg */ 22522944501Smrg struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1]; 22622944501Smrg unsigned int texAge[MGA_NR_TEX_HEAPS]; 22722944501Smrg 22822944501Smrg /* Mechanism to validate card state. 22922944501Smrg */ 23022944501Smrg int ctxOwner; 23122944501Smrg} drm_mga_sarea_t; 23222944501Smrg 23322944501Smrg/* MGA specific ioctls 23422944501Smrg * The device specific ioctl range is 0x40 to 0x79. 23522944501Smrg */ 23622944501Smrg#define DRM_MGA_INIT 0x00 23722944501Smrg#define DRM_MGA_FLUSH 0x01 23822944501Smrg#define DRM_MGA_RESET 0x02 23922944501Smrg#define DRM_MGA_SWAP 0x03 24022944501Smrg#define DRM_MGA_CLEAR 0x04 24122944501Smrg#define DRM_MGA_VERTEX 0x05 24222944501Smrg#define DRM_MGA_INDICES 0x06 24322944501Smrg#define DRM_MGA_ILOAD 0x07 24422944501Smrg#define DRM_MGA_BLIT 0x08 24522944501Smrg#define DRM_MGA_GETPARAM 0x09 24622944501Smrg 24722944501Smrg/* 3.2: 24822944501Smrg * ioctls for operating on fences. 24922944501Smrg */ 25022944501Smrg#define DRM_MGA_SET_FENCE 0x0a 25122944501Smrg#define DRM_MGA_WAIT_FENCE 0x0b 25222944501Smrg#define DRM_MGA_DMA_BOOTSTRAP 0x0c 25322944501Smrg 25422944501Smrg#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) 25500a23bdaSmrg#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) 25622944501Smrg#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) 25722944501Smrg#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) 25822944501Smrg#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) 25922944501Smrg#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) 26022944501Smrg#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) 26122944501Smrg#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) 26222944501Smrg#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) 26322944501Smrg#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) 26422944501Smrg#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, __u32) 26522944501Smrg#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, __u32) 26622944501Smrg#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) 26722944501Smrg 26822944501Smrgtypedef struct _drm_mga_warp_index { 26922944501Smrg int installed; 27022944501Smrg unsigned long phys_addr; 27122944501Smrg int size; 27222944501Smrg} drm_mga_warp_index_t; 27322944501Smrg 27422944501Smrgtypedef struct drm_mga_init { 27522944501Smrg enum { 27622944501Smrg MGA_INIT_DMA = 0x01, 27722944501Smrg MGA_CLEANUP_DMA = 0x02 27822944501Smrg } func; 27922944501Smrg 28022944501Smrg unsigned long sarea_priv_offset; 28122944501Smrg 28222944501Smrg int chipset; 28322944501Smrg int sgram; 28422944501Smrg 28522944501Smrg unsigned int maccess; 28622944501Smrg 28722944501Smrg unsigned int fb_cpp; 28822944501Smrg unsigned int front_offset, front_pitch; 28922944501Smrg unsigned int back_offset, back_pitch; 29022944501Smrg 29122944501Smrg unsigned int depth_cpp; 29222944501Smrg unsigned int depth_offset, depth_pitch; 29322944501Smrg 29422944501Smrg unsigned int texture_offset[MGA_NR_TEX_HEAPS]; 29522944501Smrg unsigned int texture_size[MGA_NR_TEX_HEAPS]; 29622944501Smrg 29722944501Smrg unsigned long fb_offset; 29822944501Smrg unsigned long mmio_offset; 29922944501Smrg unsigned long status_offset; 30022944501Smrg unsigned long warp_offset; 30122944501Smrg unsigned long primary_offset; 30222944501Smrg unsigned long buffers_offset; 30322944501Smrg} drm_mga_init_t; 30422944501Smrg 30522944501Smrgtypedef struct drm_mga_dma_bootstrap { 30622944501Smrg /** 30722944501Smrg * \name AGP texture region 30822944501Smrg * 30922944501Smrg * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will 31022944501Smrg * be filled in with the actual AGP texture settings. 31122944501Smrg * 31222944501Smrg * \warning 31322944501Smrg * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode 31422944501Smrg * is zero, it means that PCI memory (most likely through the use of 31522944501Smrg * an IOMMU) is being used for "AGP" textures. 31622944501Smrg */ 31722944501Smrg /*@{ */ 31822944501Smrg unsigned long texture_handle; /**< Handle used to map AGP textures. */ 31922944501Smrg __u32 texture_size; /**< Size of the AGP texture region. */ 32022944501Smrg /*@} */ 32122944501Smrg 32222944501Smrg /** 32322944501Smrg * Requested size of the primary DMA region. 32422944501Smrg * 32522944501Smrg * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be 32622944501Smrg * filled in with the actual AGP mode. If AGP was not available 32722944501Smrg */ 32822944501Smrg __u32 primary_size; 32922944501Smrg 33022944501Smrg /** 33122944501Smrg * Requested number of secondary DMA buffers. 33222944501Smrg * 33322944501Smrg * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be 33422944501Smrg * filled in with the actual number of secondary DMA buffers 33522944501Smrg * allocated. Particularly when PCI DMA is used, this may be 33622944501Smrg * (subtantially) less than the number requested. 33722944501Smrg */ 33822944501Smrg __u32 secondary_bin_count; 33922944501Smrg 34022944501Smrg /** 34122944501Smrg * Requested size of each secondary DMA buffer. 34222944501Smrg * 34322944501Smrg * While the kernel \b is free to reduce 34422944501Smrg * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed 34522944501Smrg * to reduce dma_mga_dma_bootstrap::secondary_bin_size. 34622944501Smrg */ 34722944501Smrg __u32 secondary_bin_size; 34822944501Smrg 34922944501Smrg /** 35022944501Smrg * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, 35122944501Smrg * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is 35222944501Smrg * zero, it means that PCI DMA should be used, even if AGP is 35322944501Smrg * possible. 35422944501Smrg * 35522944501Smrg * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be 35622944501Smrg * filled in with the actual AGP mode. If AGP was not available 35722944501Smrg * (i.e., PCI DMA was used), this value will be zero. 35822944501Smrg */ 35922944501Smrg __u32 agp_mode; 36022944501Smrg 36122944501Smrg /** 36222944501Smrg * Desired AGP GART size, measured in megabytes. 36322944501Smrg */ 36422944501Smrg __u8 agp_size; 36522944501Smrg} drm_mga_dma_bootstrap_t; 36622944501Smrg 36722944501Smrgtypedef struct drm_mga_clear { 36822944501Smrg unsigned int flags; 36922944501Smrg unsigned int clear_color; 37022944501Smrg unsigned int clear_depth; 37122944501Smrg unsigned int color_mask; 37222944501Smrg unsigned int depth_mask; 37322944501Smrg} drm_mga_clear_t; 37422944501Smrg 37522944501Smrgtypedef struct drm_mga_vertex { 37622944501Smrg int idx; /* buffer to queue */ 37722944501Smrg int used; /* bytes in use */ 37822944501Smrg int discard; /* client finished with buffer? */ 37922944501Smrg} drm_mga_vertex_t; 38022944501Smrg 38122944501Smrgtypedef struct drm_mga_indices { 38222944501Smrg int idx; /* buffer to queue */ 38322944501Smrg unsigned int start; 38422944501Smrg unsigned int end; 38522944501Smrg int discard; /* client finished with buffer? */ 38622944501Smrg} drm_mga_indices_t; 38722944501Smrg 38822944501Smrgtypedef struct drm_mga_iload { 38922944501Smrg int idx; 39022944501Smrg unsigned int dstorg; 39122944501Smrg unsigned int length; 39222944501Smrg} drm_mga_iload_t; 39322944501Smrg 39422944501Smrgtypedef struct _drm_mga_blit { 39522944501Smrg unsigned int planemask; 39622944501Smrg unsigned int srcorg; 39722944501Smrg unsigned int dstorg; 39822944501Smrg int src_pitch, dst_pitch; 39922944501Smrg int delta_sx, delta_sy; 40022944501Smrg int delta_dx, delta_dy; 40122944501Smrg int height, ydir; /* flip image vertically */ 40222944501Smrg int source_pitch, dest_pitch; 40322944501Smrg} drm_mga_blit_t; 40422944501Smrg 40522944501Smrg/* 3.1: An ioctl to get parameters that aren't available to the 3d 40622944501Smrg * client any other way. 40722944501Smrg */ 40822944501Smrg#define MGA_PARAM_IRQ_NR 1 40922944501Smrg 41022944501Smrg/* 3.2: Query the actual card type. The DDX only distinguishes between 41122944501Smrg * G200 chips and non-G200 chips, which it calls G400. It turns out that 41222944501Smrg * there are some very sublte differences between the G4x0 chips and the G550 41322944501Smrg * chips. Using this parameter query, a client-side driver can detect the 41422944501Smrg * difference between a G4x0 and a G550. 41522944501Smrg */ 41622944501Smrg#define MGA_PARAM_CARD_TYPE 2 41722944501Smrg 41822944501Smrgtypedef struct drm_mga_getparam { 41922944501Smrg int param; 42022944501Smrg void *value; 42122944501Smrg} drm_mga_getparam_t; 42222944501Smrg 42300a23bdaSmrg#if defined(__cplusplus) 42400a23bdaSmrg} 42500a23bdaSmrg#endif 42600a23bdaSmrg 42722944501Smrg#endif 428