Virtio::Virtio(hw::PCI_Device& dev) : _pcidev(dev), _virtio_device_id(dev.product_id() + 0x1040) { INFO("Virtio","Attaching to PCI addr 0x%x",_pcidev.pci_addr()); /** PCI Device discovery. Virtio std. §4.1.2 */ /** Match vendor ID and Device ID : §4.1.2.2 */ if (_pcidev.vendor_id() != hw::PCI_Device::VENDOR_VIRTIO) panic("This is not a Virtio device"); CHECK(true, "Vendor ID is VIRTIO"); bool _STD_ID = _virtio_device_id >= 0x1040 and _virtio_device_id < 0x107f; bool _LEGACY_ID = _pcidev.product_id() >= 0x1000 and _pcidev.product_id() <= 0x103f; CHECK(_STD_ID or _LEGACY_ID, "Device ID 0x%x is in a valid range (%s)", _pcidev.product_id(), _STD_ID ? ">= Virtio 1.0" : (_LEGACY_ID ? "Virtio LEGACY" : "INVALID")); assert(_STD_ID or _LEGACY_ID); /** Match Device revision ID. Virtio Std. §4.1.2.2 */ bool rev_id_ok = ((_LEGACY_ID and _pcidev.rev_id() == 0) or (_STD_ID and _pcidev.rev_id() > 0)); CHECK(rev_id_ok and version_supported(_pcidev.rev_id()), "Device Revision ID (0x%x) supported", _pcidev.rev_id()); assert(rev_id_ok); // We'll try to continue if it's newer than supported. // Probe PCI resources and fetch I/O-base for device _pcidev.probe_resources(); _iobase=_pcidev.iobase(); CHECK(_iobase, "Unit has valid I/O base (0x%x)", _iobase); /** Device initialization. Virtio Std. v.1, sect. 3.1: */ // 1. Reset device reset(); INFO2("[*] Reset device"); // 2. Set ACKNOWLEGE status bit, and // 3. Set DRIVER status bit hw::outp(_iobase + VIRTIO_PCI_STATUS, hw::inp(_iobase + VIRTIO_PCI_STATUS) | VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER); // THE REMAINING STEPS MUST BE DONE IN A SUBCLASS // 4. Negotiate features (Read, write, read) // => In the subclass (i.e. Only the Nic driver knows if it wants a mac) // 5. @todo IF >= Virtio 1.0, set FEATURES_OK status bit // 6. @todo IF >= Virtio 1.0, Re-read Device Status to ensure features are OK // 7. Device specifig setup. // Where the standard isn't clear, we'll do our best to separate work // between this class and subclasses. //Fetch IRQ from PCI resource set_irq(); CHECK(_irq, "Unit has IRQ %i", _irq); INFO("Virtio","Enabling IRQ Handler"); enable_irq_handler(); INFO("Virtio", "Initialization complete"); // It would be nice if we new that all queues were the same size. // Then we could pass this size on to the device-specific constructor // But, it seems there aren't any guarantees in the standard. // @note this is "the Legacy interface" according to Virtio std. 4.1.4.8. // uint32_t queue_size = hw::inpd(_iobase + 0x0C); /* printf(queue_size > 0 and queue_size != PCI_WTF ? "\t [x] Queue Size : 0x%lx \n" : "\t [ ] No qeuue Size? : 0x%lx \n" ,queue_size); */ }
/** * Print interesting OpenGL implementation limits. * \param version 20, 21, 30, 31, 32, etc. */ void print_limits(const char *extensions, const char *oglstring, int version, const struct ext_functions *extfuncs) { struct token_name { GLuint count; GLenum token; const char *name; const char *extension; /* NULL or GL extension name or version string */ }; static const struct token_name limits[] = { { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH", NULL }, { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH", NULL }, { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES", NULL }, { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH", "GL_ARB_imaging" }, { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES", NULL }, { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES", NULL }, { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER", NULL }, { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS", NULL }, { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING", NULL }, { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH", NULL }, { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH", NULL }, { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE", NULL }, { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH", NULL }, { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH", NULL }, { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE", NULL }, { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE", NULL }, #if defined(GL_EXT_texture_array) { 1, GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, "GL_MAX_ARRAY_TEXTURE_LAYERS", "GL_EXT_texture_array" }, #endif { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS", NULL }, { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE", NULL }, { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE", NULL }, { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE", NULL }, { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE", NULL }, #if defined(GL_ARB_texture_cube_map) { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB", "GL_ARB_texture_cube_map" }, #endif #if defined(GL_NV_texture_rectangle) { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV", "GL_NV_texture_rectangle" }, #endif #if defined(GL_ARB_multitexture) { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB", "GL_ARB_multitexture" }, #endif #if defined(GL_EXT_texture_lod_bias) { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT", "GL_EXT_texture_lod_bias" }, #endif #if defined(GL_EXT_texture_filter_anisotropic) { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT", "GL_EXT_texture_filter_anisotropic" }, #endif #if defined(GL_ARB_draw_buffers) { 1, GL_MAX_DRAW_BUFFERS_ARB, "GL_MAX_DRAW_BUFFERS_ARB", "GL_ARB_draw_buffers" }, #endif #if defined(GL_ARB_blend_func_extended) { 1, GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS", "GL_ARB_blend_func_extended" }, #endif #if defined (GL_ARB_framebuffer_object) { 1, GL_MAX_RENDERBUFFER_SIZE, "GL_MAX_RENDERBUFFER_SIZE", "GL_ARB_framebuffer_object" }, { 1, GL_MAX_COLOR_ATTACHMENTS, "GL_MAX_COLOR_ATTACHMENTS", "GL_ARB_framebuffer_object" }, { 1, GL_MAX_SAMPLES, "GL_MAX_SAMPLES", "GL_ARB_framebuffer_object" }, #endif #if defined (GL_EXT_transform_feedback) { 1, GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS", "GL_EXT_transform_feedback" }, { 1, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT, "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", "GL_EXT_transform_feedback" }, { 1, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT, "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", "GL_EXT_transform_feedback", }, { 1, GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT, "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS", "GL_EXT_transform_feedback" }, #endif #if defined (GL_ARB_texture_buffer_object) { 1, GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT", "GL_ARB_texture_buffer_object" }, { 1, GL_MAX_TEXTURE_BUFFER_SIZE, "GL_MAX_TEXTURE_BUFFER_SIZE", "GL_ARB_texture_buffer_object" }, #endif #if defined (GL_ARB_texture_multisample) { 1, GL_MAX_COLOR_TEXTURE_SAMPLES, "GL_MAX_COLOR_TEXTURE_SAMPLES", "GL_ARB_texture_multisample" }, { 1, GL_MAX_DEPTH_TEXTURE_SAMPLES, "GL_MAX_DEPTH_TEXTURE_SAMPLES", "GL_ARB_texture_multisample" }, { 1, GL_MAX_INTEGER_SAMPLES, "GL_MAX_INTEGER_SAMPLES", "GL_ARB_texture_multisample" }, #endif #if defined (GL_ARB_uniform_buffer_object) { 1, GL_MAX_VERTEX_UNIFORM_BLOCKS, "GL_MAX_VERTEX_UNIFORM_BLOCKS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, "GL_MAX_FRAGMENT_UNIFORM_BLOCKS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_GEOMETRY_UNIFORM_BLOCKS, "GL_MAX_GEOMETRY_UNIFORM_BLOCKS" , "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_UNIFORM_BLOCKS, "GL_MAX_COMBINED_UNIFORM_BLOCKS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_UNIFORM_BUFFER_BINDINGS, "GL_MAX_UNIFORM_BUFFER_BINDINGS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_UNIFORM_BLOCK_SIZE, "GL_MAX_UNIFORM_BLOCK_SIZE", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", "GL_ARB_uniform_buffer_object" }, { 1, GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS", "GL_ARB_uniform_buffer_object" }, { 1, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT", "GL_ARB_uniform_buffer_object" }, #endif #if defined (GL_ARB_vertex_attrib_binding) { 1, GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", "GL_ARB_vertex_attrib_binding" }, { 1, GL_MAX_VERTEX_ATTRIB_BINDINGS, "GL_MAX_VERTEX_ATTRIB_BINDINGS", "GL_ARB_vertex_attrib_binding" }, #endif #if defined(GL_VERSION_4_4) { 1, GL_MAX_VERTEX_ATTRIB_STRIDE, "GL_MAX_VERTEX_ATTRIB_STRIDE", "4.4" }, #endif { 0, (GLenum) 0, NULL, NULL } }; GLint i, max[2]; printf("%s limits:\n", oglstring); for (i = 0; limits[i].count; i++) { if (!limits[i].extension || version_supported(limits[i].extension, version) || extension_supported(limits[i].extension, extensions)) { glGetIntegerv(limits[i].token, max); if (glGetError() == GL_NO_ERROR) { if (limits[i].count == 1) printf(" %s = %d\n", limits[i].name, max[0]); else /* XXX fix if we ever query something with more than 2 values */ printf(" %s = %d, %d\n", limits[i].name, max[0], max[1]); } } } /* these don't fit into the above mechanism, unfortunately */ if (extension_supported("GL_ARB_imaging", extensions)) { extfuncs->GetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_WIDTH, max); extfuncs->GetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_HEIGHT, max+1); printf(" GL_MAX_CONVOLUTION_WIDTH/HEIGHT = %d, %d\n", max[0], max[1]); } if (extension_supported("GL_ARB_texture_compression", extensions)) { GLint i, n; GLint *formats; glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &n); printf(" GL_NUM_COMPRESSED_TEXTURE_FORMATS = %d\n", n); formats = (GLint *) malloc(n * sizeof(GLint)); glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); for (i = 0; i < n; i++) { printf(" %s\n", enum_name(formats[i])); } free(formats); } #if defined(GL_ARB_vertex_program) if (extension_supported("GL_ARB_vertex_program", extensions)) { print_program_limits(GL_VERTEX_PROGRAM_ARB, extfuncs); } #endif #if defined(GL_ARB_fragment_program) if (extension_supported("GL_ARB_fragment_program", extensions)) { print_program_limits(GL_FRAGMENT_PROGRAM_ARB, extfuncs); } #endif if (extension_supported("GL_ARB_vertex_shader", extensions)) { print_shader_limits(GL_VERTEX_SHADER_ARB); } if (extension_supported("GL_ARB_fragment_shader", extensions)) { print_shader_limits(GL_FRAGMENT_SHADER_ARB); } if (version >= 32) { print_shader_limits(GL_GEOMETRY_SHADER); } }