1*58a2b000SEvgeniy Ivanov/* $NetBSD: biosvbe.S,v 1.3 2011/02/20 22:03:13 jakllsch Exp $ */ 2*58a2b000SEvgeniy Ivanov 3*58a2b000SEvgeniy Ivanov/*- 4*58a2b000SEvgeniy Ivanov * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca> 5*58a2b000SEvgeniy Ivanov * All rights reserved. 6*58a2b000SEvgeniy Ivanov * 7*58a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 8*58a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 9*58a2b000SEvgeniy Ivanov * are met: 10*58a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 11*58a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 12*58a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 13*58a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 14*58a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 15*58a2b000SEvgeniy Ivanov * 16*58a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17*58a2b000SEvgeniy Ivanov * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18*58a2b000SEvgeniy Ivanov * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19*58a2b000SEvgeniy Ivanov * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20*58a2b000SEvgeniy Ivanov * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21*58a2b000SEvgeniy Ivanov * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22*58a2b000SEvgeniy Ivanov * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23*58a2b000SEvgeniy Ivanov * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24*58a2b000SEvgeniy Ivanov * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25*58a2b000SEvgeniy Ivanov * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26*58a2b000SEvgeniy Ivanov * POSSIBILITY OF SUCH DAMAGE. 27*58a2b000SEvgeniy Ivanov */ 28*58a2b000SEvgeniy Ivanov 29*58a2b000SEvgeniy Ivanov#include <machine/asm.h> 30*58a2b000SEvgeniy Ivanov 31*58a2b000SEvgeniy Ivanov .text 32*58a2b000SEvgeniy Ivanov 33*58a2b000SEvgeniy Ivanov/* 34*58a2b000SEvgeniy Ivanov * VESA BIOS Extensions routines 35*58a2b000SEvgeniy Ivanov */ 36*58a2b000SEvgeniy Ivanov 37*58a2b000SEvgeniy Ivanov/* 38*58a2b000SEvgeniy Ivanov * Function 00h - Return VBE Controller Information 39*58a2b000SEvgeniy Ivanov * 40*58a2b000SEvgeniy Ivanov * int biosvbe_info(struct vbeinfoblock *) 41*58a2b000SEvgeniy Ivanov * return: VBE call status 42*58a2b000SEvgeniy Ivanov */ 43*58a2b000SEvgeniy IvanovENTRY(biosvbe_info) 44*58a2b000SEvgeniy Ivanov pushl %ebp 45*58a2b000SEvgeniy Ivanov movl %esp,%ebp 46*58a2b000SEvgeniy Ivanov pushl %ebx 47*58a2b000SEvgeniy Ivanov pushl %ecx 48*58a2b000SEvgeniy Ivanov pushl %edx 49*58a2b000SEvgeniy Ivanov push %esi 50*58a2b000SEvgeniy Ivanov push %edi 51*58a2b000SEvgeniy Ivanov 52*58a2b000SEvgeniy Ivanov movl 8(%ebp), %edi /* vbe info block address*/ 53*58a2b000SEvgeniy Ivanov 54*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 55*58a2b000SEvgeniy Ivanov .code16 56*58a2b000SEvgeniy Ivanov 57*58a2b000SEvgeniy Ivanov push %es 58*58a2b000SEvgeniy Ivanov 59*58a2b000SEvgeniy Ivanov push %di 60*58a2b000SEvgeniy Ivanov shrl $4, %edi 61*58a2b000SEvgeniy Ivanov mov %ds, %ax 62*58a2b000SEvgeniy Ivanov add %di, %ax 63*58a2b000SEvgeniy Ivanov mov %ax, %es 64*58a2b000SEvgeniy Ivanov pop %di 65*58a2b000SEvgeniy Ivanov and $0xf, %di /* mode info block address now in es:di */ 66*58a2b000SEvgeniy Ivanov 67*58a2b000SEvgeniy Ivanov movw $0x4f00, %ax /* get vbe info block */ 68*58a2b000SEvgeniy Ivanov int $0x10 69*58a2b000SEvgeniy Ivanov 70*58a2b000SEvgeniy Ivanov pop %es 71*58a2b000SEvgeniy Ivanov 72*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 73*58a2b000SEvgeniy Ivanov .code32 74*58a2b000SEvgeniy Ivanov 75*58a2b000SEvgeniy Ivanov andl $0xffff,%eax 76*58a2b000SEvgeniy Ivanov 77*58a2b000SEvgeniy Ivanov pop %edi 78*58a2b000SEvgeniy Ivanov pop %esi 79*58a2b000SEvgeniy Ivanov popl %edx 80*58a2b000SEvgeniy Ivanov popl %ecx 81*58a2b000SEvgeniy Ivanov popl %ebx 82*58a2b000SEvgeniy Ivanov popl %ebp 83*58a2b000SEvgeniy Ivanov ret 84*58a2b000SEvgeniy Ivanov 85*58a2b000SEvgeniy Ivanov/* 86*58a2b000SEvgeniy Ivanov * Function 01h - Return VBE Mode Information 87*58a2b000SEvgeniy Ivanov * 88*58a2b000SEvgeniy Ivanov * int biosvbe_get_mode_info(int mode, struct modeinfoblock *mi) 89*58a2b000SEvgeniy Ivanov * return: VBE call status 90*58a2b000SEvgeniy Ivanov */ 91*58a2b000SEvgeniy IvanovENTRY(biosvbe_get_mode_info) 92*58a2b000SEvgeniy Ivanov pushl %ebp 93*58a2b000SEvgeniy Ivanov movl %esp,%ebp 94*58a2b000SEvgeniy Ivanov pushl %ebx 95*58a2b000SEvgeniy Ivanov pushl %ecx 96*58a2b000SEvgeniy Ivanov pushl %edx 97*58a2b000SEvgeniy Ivanov push %esi 98*58a2b000SEvgeniy Ivanov push %edi 99*58a2b000SEvgeniy Ivanov 100*58a2b000SEvgeniy Ivanov movl 8(%ebp), %ecx /* mode number */ 101*58a2b000SEvgeniy Ivanov movl 12(%ebp), %edi /* mode info block address */ 102*58a2b000SEvgeniy Ivanov 103*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 104*58a2b000SEvgeniy Ivanov .code16 105*58a2b000SEvgeniy Ivanov 106*58a2b000SEvgeniy Ivanov push %es 107*58a2b000SEvgeniy Ivanov 108*58a2b000SEvgeniy Ivanov push %di 109*58a2b000SEvgeniy Ivanov shrl $4, %edi 110*58a2b000SEvgeniy Ivanov mov %ds, %ax 111*58a2b000SEvgeniy Ivanov add %di, %ax 112*58a2b000SEvgeniy Ivanov mov %ax, %es 113*58a2b000SEvgeniy Ivanov pop %di 114*58a2b000SEvgeniy Ivanov and $0xf, %di /* mode info block address now in es:di */ 115*58a2b000SEvgeniy Ivanov 116*58a2b000SEvgeniy Ivanov movw $0x4f01, %ax /* get mode info block */ 117*58a2b000SEvgeniy Ivanov int $0x10 118*58a2b000SEvgeniy Ivanov 119*58a2b000SEvgeniy Ivanov pop %es 120*58a2b000SEvgeniy Ivanov 121*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 122*58a2b000SEvgeniy Ivanov .code32 123*58a2b000SEvgeniy Ivanov 124*58a2b000SEvgeniy Ivanov andl $0xffff,%eax 125*58a2b000SEvgeniy Ivanov 126*58a2b000SEvgeniy Ivanov pop %edi 127*58a2b000SEvgeniy Ivanov pop %esi 128*58a2b000SEvgeniy Ivanov popl %edx 129*58a2b000SEvgeniy Ivanov popl %ecx 130*58a2b000SEvgeniy Ivanov popl %ebx 131*58a2b000SEvgeniy Ivanov popl %ebp 132*58a2b000SEvgeniy Ivanov ret 133*58a2b000SEvgeniy Ivanov 134*58a2b000SEvgeniy Ivanov/* 135*58a2b000SEvgeniy Ivanov * Function 02h - Set VBE Mode 136*58a2b000SEvgeniy Ivanov * 137*58a2b000SEvgeniy Ivanov * int biosvbe_set_mode(int mode) 138*58a2b000SEvgeniy Ivanov * return: VBE call status 139*58a2b000SEvgeniy Ivanov */ 140*58a2b000SEvgeniy IvanovENTRY(biosvbe_set_mode) 141*58a2b000SEvgeniy Ivanov pushl %ebp 142*58a2b000SEvgeniy Ivanov movl %esp,%ebp 143*58a2b000SEvgeniy Ivanov pushl %ebx 144*58a2b000SEvgeniy Ivanov pushl %ecx 145*58a2b000SEvgeniy Ivanov pushl %edx 146*58a2b000SEvgeniy Ivanov push %esi 147*58a2b000SEvgeniy Ivanov push %edi 148*58a2b000SEvgeniy Ivanov 149*58a2b000SEvgeniy Ivanov movl 8(%ebp), %ebx /* mode number */ 150*58a2b000SEvgeniy Ivanov orl $0x4000, %ebx 151*58a2b000SEvgeniy Ivanov 152*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 153*58a2b000SEvgeniy Ivanov .code16 154*58a2b000SEvgeniy Ivanov 155*58a2b000SEvgeniy Ivanov movw $0x4f02, %ax /* set mode */ 156*58a2b000SEvgeniy Ivanov int $0x10 157*58a2b000SEvgeniy Ivanov 158*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 159*58a2b000SEvgeniy Ivanov .code32 160*58a2b000SEvgeniy Ivanov 161*58a2b000SEvgeniy Ivanov andl $0xffff,%eax 162*58a2b000SEvgeniy Ivanov 163*58a2b000SEvgeniy Ivanov pop %edi 164*58a2b000SEvgeniy Ivanov pop %esi 165*58a2b000SEvgeniy Ivanov popl %edx 166*58a2b000SEvgeniy Ivanov popl %ecx 167*58a2b000SEvgeniy Ivanov popl %ebx 168*58a2b000SEvgeniy Ivanov popl %ebp 169*58a2b000SEvgeniy Ivanov ret 170*58a2b000SEvgeniy Ivanov 171*58a2b000SEvgeniy Ivanov/* 172*58a2b000SEvgeniy Ivanov * Function 08h - Set/Get DAC Palette Format 173*58a2b000SEvgeniy Ivanov * 174*58a2b000SEvgeniy Ivanov * int biosvbe_palette_format(int format) 175*58a2b000SEvgeniy Ivanov * return: VBE call status 176*58a2b000SEvgeniy Ivanov */ 177*58a2b000SEvgeniy IvanovENTRY(biosvbe_palette_format) 178*58a2b000SEvgeniy Ivanov pushl %ebp 179*58a2b000SEvgeniy Ivanov movl %esp,%ebp 180*58a2b000SEvgeniy Ivanov pushl %ebx 181*58a2b000SEvgeniy Ivanov pushl %ecx 182*58a2b000SEvgeniy Ivanov pushl %edx 183*58a2b000SEvgeniy Ivanov push %esi 184*58a2b000SEvgeniy Ivanov push %edi 185*58a2b000SEvgeniy Ivanov 186*58a2b000SEvgeniy Ivanov movl 8(%ebp), %ebx /* mode number */ 187*58a2b000SEvgeniy Ivanov 188*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 189*58a2b000SEvgeniy Ivanov .code16 190*58a2b000SEvgeniy Ivanov 191*58a2b000SEvgeniy Ivanov movw $0x4f08, %ax /* get/set palette format */ 192*58a2b000SEvgeniy Ivanov int $0x10 193*58a2b000SEvgeniy Ivanov 194*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 195*58a2b000SEvgeniy Ivanov .code32 196*58a2b000SEvgeniy Ivanov 197*58a2b000SEvgeniy Ivanov andl $0xffff,%eax 198*58a2b000SEvgeniy Ivanov 199*58a2b000SEvgeniy Ivanov pop %edi 200*58a2b000SEvgeniy Ivanov pop %esi 201*58a2b000SEvgeniy Ivanov popl %edx 202*58a2b000SEvgeniy Ivanov popl %ecx 203*58a2b000SEvgeniy Ivanov popl %ebx 204*58a2b000SEvgeniy Ivanov popl %ebp 205*58a2b000SEvgeniy Ivanov ret 206*58a2b000SEvgeniy Ivanov 207*58a2b000SEvgeniy Ivanov/* 208*58a2b000SEvgeniy Ivanov * Function 09h - Set/Get Palette Data 209*58a2b000SEvgeniy Ivanov * 210*58a2b000SEvgeniy Ivanov * int biosvbe_palette_data(int mode, int reg, struct paletteentry *) 211*58a2b000SEvgeniy Ivanov * return: VBE call status 212*58a2b000SEvgeniy Ivanov */ 213*58a2b000SEvgeniy IvanovENTRY(biosvbe_palette_data) 214*58a2b000SEvgeniy Ivanov pushl %ebp 215*58a2b000SEvgeniy Ivanov movl %esp,%ebp 216*58a2b000SEvgeniy Ivanov pushl %ebx 217*58a2b000SEvgeniy Ivanov pushl %ecx 218*58a2b000SEvgeniy Ivanov pushl %edx 219*58a2b000SEvgeniy Ivanov push %esi 220*58a2b000SEvgeniy Ivanov push %edi 221*58a2b000SEvgeniy Ivanov 222*58a2b000SEvgeniy Ivanov movl 8(%ebp), %ebx /* mode number */ 223*58a2b000SEvgeniy Ivanov movl 12(%ebp), %edx /* register */ 224*58a2b000SEvgeniy Ivanov movl 16(%ebp), %edi /* palette entry address */ 225*58a2b000SEvgeniy Ivanov movl $1, %ecx /* # palette entries to update */ 226*58a2b000SEvgeniy Ivanov 227*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 228*58a2b000SEvgeniy Ivanov .code16 229*58a2b000SEvgeniy Ivanov 230*58a2b000SEvgeniy Ivanov push %es 231*58a2b000SEvgeniy Ivanov 232*58a2b000SEvgeniy Ivanov push %di 233*58a2b000SEvgeniy Ivanov shrl $4, %edi 234*58a2b000SEvgeniy Ivanov mov %ds, %ax 235*58a2b000SEvgeniy Ivanov add %di, %ax 236*58a2b000SEvgeniy Ivanov mov %ax, %es 237*58a2b000SEvgeniy Ivanov pop %di 238*58a2b000SEvgeniy Ivanov and $0xf, %di /* palette entry address now in es:di */ 239*58a2b000SEvgeniy Ivanov 240*58a2b000SEvgeniy Ivanov movw $0x4f09, %ax /* get/set palette entry */ 241*58a2b000SEvgeniy Ivanov int $0x10 242*58a2b000SEvgeniy Ivanov 243*58a2b000SEvgeniy Ivanov pop %es 244*58a2b000SEvgeniy Ivanov 245*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 246*58a2b000SEvgeniy Ivanov .code32 247*58a2b000SEvgeniy Ivanov 248*58a2b000SEvgeniy Ivanov andl $0xffff,%eax 249*58a2b000SEvgeniy Ivanov 250*58a2b000SEvgeniy Ivanov pop %edi 251*58a2b000SEvgeniy Ivanov pop %esi 252*58a2b000SEvgeniy Ivanov popl %edx 253*58a2b000SEvgeniy Ivanov popl %ecx 254*58a2b000SEvgeniy Ivanov popl %ebx 255*58a2b000SEvgeniy Ivanov popl %ebp 256*58a2b000SEvgeniy Ivanov ret 257*58a2b000SEvgeniy Ivanov 258*58a2b000SEvgeniy Ivanov/* 259*58a2b000SEvgeniy Ivanov * Function 15h BL=00h - Report VBE/DDC Capabilities 260*58a2b000SEvgeniy Ivanov * 261*58a2b000SEvgeniy Ivanov * int biosvbe_ddc_caps(void) 262*58a2b000SEvgeniy Ivanov * return: VBE/DDC capabilities 263*58a2b000SEvgeniy Ivanov */ 264*58a2b000SEvgeniy IvanovENTRY(biosvbe_ddc_caps) 265*58a2b000SEvgeniy Ivanov pushl %ebp 266*58a2b000SEvgeniy Ivanov movl %esp,%ebp 267*58a2b000SEvgeniy Ivanov pushl %ebx 268*58a2b000SEvgeniy Ivanov pushl %ecx 269*58a2b000SEvgeniy Ivanov pushl %edx 270*58a2b000SEvgeniy Ivanov push %esi 271*58a2b000SEvgeniy Ivanov push %edi 272*58a2b000SEvgeniy Ivanov 273*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 274*58a2b000SEvgeniy Ivanov .code16 275*58a2b000SEvgeniy Ivanov 276*58a2b000SEvgeniy Ivanov pushw %es 277*58a2b000SEvgeniy Ivanov 278*58a2b000SEvgeniy Ivanov xorw %di, %di 279*58a2b000SEvgeniy Ivanov movw %di, %es /* es:di == 0:0 */ 280*58a2b000SEvgeniy Ivanov 281*58a2b000SEvgeniy Ivanov movw $0x4f15, %ax /* display identification extensions */ 282*58a2b000SEvgeniy Ivanov mov $0x00, %bx /* report DDC capabilities */ 283*58a2b000SEvgeniy Ivanov mov $0x00, %cx /* controller unit number (00h = primary) */ 284*58a2b000SEvgeniy Ivanov int $0x10 285*58a2b000SEvgeniy Ivanov 286*58a2b000SEvgeniy Ivanov popw %es 287*58a2b000SEvgeniy Ivanov 288*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 289*58a2b000SEvgeniy Ivanov .code32 290*58a2b000SEvgeniy Ivanov 291*58a2b000SEvgeniy Ivanov movl %eax,%ecx 292*58a2b000SEvgeniy Ivanov movl $0x0000,%eax 293*58a2b000SEvgeniy Ivanov andl $0xffff,%ecx 294*58a2b000SEvgeniy Ivanov cmpl $0x004f,%ecx 295*58a2b000SEvgeniy Ivanov jne 1f 296*58a2b000SEvgeniy Ivanov andl $0xffff,%ebx 297*58a2b000SEvgeniy Ivanov movl %ebx,%eax 298*58a2b000SEvgeniy Ivanov1: 299*58a2b000SEvgeniy Ivanov 300*58a2b000SEvgeniy Ivanov pop %edi 301*58a2b000SEvgeniy Ivanov pop %esi 302*58a2b000SEvgeniy Ivanov popl %edx 303*58a2b000SEvgeniy Ivanov popl %ecx 304*58a2b000SEvgeniy Ivanov popl %ebx 305*58a2b000SEvgeniy Ivanov popl %ebp 306*58a2b000SEvgeniy Ivanov ret 307*58a2b000SEvgeniy Ivanov 308*58a2b000SEvgeniy Ivanov/* 309*58a2b000SEvgeniy Ivanov * Function 15h BL=01h - Read EDID 310*58a2b000SEvgeniy Ivanov * 311*58a2b000SEvgeniy Ivanov * int biosvbe_ddc_read_edid(int blockno, void *buf) 312*58a2b000SEvgeniy Ivanov * return: VBE call status 313*58a2b000SEvgeniy Ivanov */ 314*58a2b000SEvgeniy IvanovENTRY(biosvbe_ddc_read_edid) 315*58a2b000SEvgeniy Ivanov pushl %ebp 316*58a2b000SEvgeniy Ivanov movl %esp,%ebp 317*58a2b000SEvgeniy Ivanov pushl %ebx 318*58a2b000SEvgeniy Ivanov pushl %ecx 319*58a2b000SEvgeniy Ivanov pushl %edx 320*58a2b000SEvgeniy Ivanov push %esi 321*58a2b000SEvgeniy Ivanov push %edi 322*58a2b000SEvgeniy Ivanov 323*58a2b000SEvgeniy Ivanov movl 8(%ebp), %edx /* EDID block number */ 324*58a2b000SEvgeniy Ivanov movl 12(%ebp), %edi /* EDID block address */ 325*58a2b000SEvgeniy Ivanov 326*58a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) 327*58a2b000SEvgeniy Ivanov .code16 328*58a2b000SEvgeniy Ivanov 329*58a2b000SEvgeniy Ivanov push %es 330*58a2b000SEvgeniy Ivanov 331*58a2b000SEvgeniy Ivanov push %di 332*58a2b000SEvgeniy Ivanov shrl $4, %edi 333*58a2b000SEvgeniy Ivanov mov %ds, %ax 334*58a2b000SEvgeniy Ivanov add %di, %ax 335*58a2b000SEvgeniy Ivanov mov %ax, %es 336*58a2b000SEvgeniy Ivanov pop %di 337*58a2b000SEvgeniy Ivanov and $0xf, %di /* EDID block address now in es:di */ 338*58a2b000SEvgeniy Ivanov 339*58a2b000SEvgeniy Ivanov movw $0x4f15, %ax /* display identification extensions */ 340*58a2b000SEvgeniy Ivanov mov $0x01, %bx /* read EDID */ 341*58a2b000SEvgeniy Ivanov mov $0x00, %cx /* controller unit number (00h = primary) */ 342*58a2b000SEvgeniy Ivanov int $0x10 343*58a2b000SEvgeniy Ivanov 344*58a2b000SEvgeniy Ivanov pop %es 345*58a2b000SEvgeniy Ivanov 346*58a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) 347*58a2b000SEvgeniy Ivanov .code32 348*58a2b000SEvgeniy Ivanov 349*58a2b000SEvgeniy Ivanov andl $0xffff,%eax 350*58a2b000SEvgeniy Ivanov 351*58a2b000SEvgeniy Ivanov pop %edi 352*58a2b000SEvgeniy Ivanov pop %esi 353*58a2b000SEvgeniy Ivanov popl %edx 354*58a2b000SEvgeniy Ivanov popl %ecx 355*58a2b000SEvgeniy Ivanov popl %ebx 356*58a2b000SEvgeniy Ivanov popl %ebp 357*58a2b000SEvgeniy Ivanov ret 358*58a2b000SEvgeniy Ivanov 359