diff --git a/clext.c b/clext.c
index c7a2ad0..b0b6834 100644
--- a/clext.c
+++ b/clext.c
@@ -948,7 +948,8 @@ cirrus_vesa_01h_3:
   ;; 32-bit LFB address
   xor ax, ax
   stosw
-  call cirrus_get_lfb_addr
+  mov ax, #0x1013 ;; vendor Cirrus
+  call _pci_get_lfb_addr
   stosw
   or ax, ax
   jz cirrus_vesa_01h_4
@@ -1293,54 +1294,6 @@ cgm_2:
 cgm_3:
   ret
 
-  ; get LFB address
-  ; out - ax:LFB address (high 16 bit)
-  ;; NOTE - may be called in protected mode
-cirrus_get_lfb_addr:
-  push cx
-  push dx
-  push eax
-    xor cx, cx
-    mov dl, #0x00
-    call cirrus_pci_read
-    cmp ax, #0xffff
-    jz cirrus_get_lfb_addr_5
- cirrus_get_lfb_addr_3:
-    mov dl, #0x00
-    call cirrus_pci_read
-    cmp ax, #0x1013 ;; cirrus
-    jz cirrus_get_lfb_addr_4
-    add cx, #0x8
-    cmp cx, #0x200 ;; search bus #0 and #1
-    jb cirrus_get_lfb_addr_3
- cirrus_get_lfb_addr_5:
-    xor dx, dx ;; no LFB
-    jmp cirrus_get_lfb_addr_6
- cirrus_get_lfb_addr_4:
-    mov dl, #0x10 ;; I/O space #0
-    call cirrus_pci_read
-    test ax, #0xfff1
-    jnz cirrus_get_lfb_addr_5
-    shr eax, #16
-    mov dx, ax ;; LFB address
- cirrus_get_lfb_addr_6:
-  pop eax
-  mov ax, dx
-  pop dx
-  pop cx
-  ret
-
-cirrus_pci_read:
-  mov eax, #0x00800000
-  mov ax, cx
-  shl eax, #8
-  mov al, dl
-  mov dx, #0xcf8
-  out dx, eax
-  add dl, #4
-  in  eax, dx
-  ret
-
 ;; out - al:bytes per pixel
 cirrus_get_bpp_bytes:
   push dx
diff --git a/vbe.c b/vbe.c
index 6173ca0..92e3d0d 100644
--- a/vbe.c
+++ b/vbe.c
@@ -766,9 +766,9 @@ Bit16u *AX;Bit16u ES;Bit16u DI;
         Bit16u            cur_mode=0;
         Bit16u            cur_ptr=34;
         ModeInfoListItem  *cur_info=&mode_info_list;
-        
+
         status = read_word(ss, AX);
-        
+
 #ifdef DEBUG
         printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
 #endif
@@ -784,7 +784,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI;
              (vbe_info_block.VbeSignature[1] == 'B') &&
              (vbe_info_block.VbeSignature[2] == 'E') &&
              (vbe_info_block.VbeSignature[3] == '2')) ||
-             
+
             ((vbe_info_block.VbeSignature[0] == 'V') &&
              (vbe_info_block.VbeSignature[1] == 'E') &&
              (vbe_info_block.VbeSignature[2] == 'S') &&
@@ -796,20 +796,20 @@ Bit16u *AX;Bit16u ES;Bit16u DI;
 #endif
         }
 #endif
-                
+
         // VBE Signature
         vbe_info_block.VbeSignature[0] = 'V';
         vbe_info_block.VbeSignature[1] = 'E';
         vbe_info_block.VbeSignature[2] = 'S';
         vbe_info_block.VbeSignature[3] = 'A';
-        
+
         // VBE Version supported
         vbe_info_block.VbeVersion = 0x0200;
-        
+
         // OEM String
         vbe_info_block.OemStringPtr_Seg = 0xc000;
         vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
-        
+
         // Capabilities
         vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
         vbe_info_block.Capabilities[1] = 0;
@@ -824,7 +824,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI;
         vbe_info_block.TotalMemory = VBE_TOTAL_VIDEO_MEMORY_DIV_64K;
 
         if (vbe2_info)
-	{
+        {
                 // OEM Stuff
                 vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
                 vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
@@ -837,12 +837,12 @@ Bit16u *AX;Bit16u ES;Bit16u DI;
                 // copy updates in vbe_info_block back
                 memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
         }
-	else
-	{
+        else
+        {
                 // copy updates in vbe_info_block back (VBE 1.x compatibility)
                 memcpyb(ES, DI, ss, &vbe_info_block, 256);
-	}
-                
+        }
+
         do
         {
                 if ((cur_info->info.XResolution <= dispi_get_max_xres()) &&
@@ -860,7 +860,7 @@ Bit16u *AX;Bit16u ES;Bit16u DI;
                 }
                 cur_info++;
         } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
-        
+
         // Add vesa mode list terminator
         write_word(ES, DI + cur_ptr, cur_info->mode);
 
@@ -888,32 +888,37 @@ Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
         ModeInfoBlock     info;
         ModeInfoListItem  *cur_info;
         Boolean           using_lfb;
+        Bit16u            lfb_addr;
 
 #ifdef DEBUG
         printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
 #endif
 
         using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
-        
+
         CX = (CX & 0x1ff);
-        
+
         cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
 
         if (cur_info != 0)
         {
 #ifdef DEBUG
                 printf("VBE found mode %x\n",CX);
-#endif        
+#endif
                 memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
                 memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
                 if (using_lfb) {
                   info.NumberOfBanks = 1;
                 }
+                lfb_addr = pci_get_lfb_addr(0x1234); // experimental vendor
+                if (lfb_addr > 0) {
+                  info.PhysBasePtr = ((Bit32u)lfb_addr << 16);
+                }
                 if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
                   info.WinFuncPtr = 0xC0000000UL;
                   *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
                 }
-                
+
                 result = 0x4f;
         }
         else
@@ -923,7 +928,7 @@ Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
 #endif
                 result = 0x100;
         }
-        
+
         if (result == 0x4f)
         {
                 // copy updates in mode_info_block back
@@ -960,21 +965,21 @@ Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
         BX = (BX & 0x1ff);
 
         //result=read_word(ss,AX);
-        
+
         // check for non vesa mode
         if (BX<VBE_MODE_VESA_DEFINED)
         {
                 Bit8u   mode;
-                
+
                 dispi_set_enable(VBE_DISPI_DISABLED);
                 // call the vgabios in order to set the video mode
                 // this allows for going back to textmode with a VBE call (some applications expect that to work)
-                
+
                 mode=(BX & 0xff);
                 biosfn_set_video_mode(mode);
                 result = 0x4f;
         }
-        
+
         cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
 
         if (cur_info != 0)
@@ -986,7 +991,7 @@ Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
                         cur_info->info.YResolution,
                         cur_info->info.BitsPerPixel);
 #endif
-                
+
                 // first disable current mode (when switching between vesa modi)
                 dispi_set_enable(VBE_DISPI_DISABLED);
 
@@ -1005,15 +1010,15 @@ Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
                 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
                 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
 
-                result = 0x4f;                  
+                result = 0x4f;
         }
         else
         {
 #ifdef DEBUG
                 printf("VBE *NOT* found mode %x\n" , BX);
-#endif        
+#endif
                 result = 0x100;
-                
+
                 // FIXME: redirect non VBE modi to normal VGA bios operation
                 //        (switch back to VGA mode
                 if (BX == 3)
@@ -1089,7 +1094,7 @@ void vbe_biosfn_restore_video_state(ES, BX)
 
     enable = read_word(ES, BX);
     BX += 2;
-    
+
     if (!(enable & VBE_DISPI_ENABLED)) {
         outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
         outw(VBE_DISPI_IOPORT_DATA, enable);
diff --git a/vgabios.c b/vgabios.c
index e6fe2a0..fbc3588 100644
--- a/vgabios.c
+++ b/vgabios.c
@@ -3830,6 +3830,64 @@ void printf(s)
 }
 #endif
 
+ASM_START
+  ; get LFB address from PCI
+  ; in - ax: PCI device vendor
+  ; out - ax: LFB address (high 16 bit)
+  ;; NOTE - may be called in protected mode
+_pci_get_lfb_addr:
+  push bx
+  push cx
+  push dx
+  push eax
+    mov bx, ax
+    xor cx, cx
+    mov dl, #0x00
+    call pci_read_reg
+    cmp ax, #0xffff
+    jz pci_get_lfb_addr_5
+ pci_get_lfb_addr_3:
+    mov dl, #0x00
+    call pci_read_reg
+    cmp ax, bx ;; check vendor
+    jz pci_get_lfb_addr_4
+    add cx, #0x8
+    cmp cx, #0x200 ;; search bus #0 and #1
+    jb pci_get_lfb_addr_3
+ pci_get_lfb_addr_5:
+    xor dx, dx ;; no LFB
+    jmp pci_get_lfb_addr_6
+ pci_get_lfb_addr_4:
+    mov dl, #0x10 ;; I/O space #0
+    call pci_read_reg
+    test ax, #0xfff1
+    jnz pci_get_lfb_addr_5
+    shr eax, #16
+    mov dx, ax ;; LFB address
+ pci_get_lfb_addr_6:
+  pop eax
+  mov ax, dx
+  pop dx
+  pop cx
+  pop bx
+  ret
+
+  ; read PCI register
+  ; in - cx: device/function
+  ; in - dl: register
+  ; out - eax: value
+pci_read_reg:
+  mov eax, #0x00800000
+  mov ax, cx
+  shl eax, #8
+  mov al, dl
+  mov dx, #0xcf8
+  out dx, eax
+  add dl, #4
+  in  eax, dx
+  ret
+ASM_END
+
 #ifdef VBE
 #include "vbe.c"
 #endif
