20 #include "VbeDisplay.h" 21 #include "modules/Module.h" 22 #include "modules/system/config/Config.h" 23 #include "pedigree/kernel/Log.h" 24 #include "pedigree/kernel/Service.h" 25 #include "pedigree/kernel/ServiceFeatures.h" 26 #include "pedigree/kernel/ServiceManager.h" 27 #include "pedigree/kernel/graphics/GraphicsService.h" 28 #include "pedigree/kernel/machine/Device.h" 29 #include "pedigree/kernel/machine/Display.h" 30 #include "pedigree/kernel/machine/Framebuffer.h" 31 #include "pedigree/kernel/machine/x86_common/Bios.h" 32 #include "pedigree/kernel/processor/MemoryRegion.h" 33 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 34 #include "pedigree/kernel/processor/VirtualAddressSpace.h" 35 #include "pedigree/kernel/processor/types.h" 36 #include "pedigree/kernel/utilities/Iterator.h" 37 #include "pedigree/kernel/utilities/List.h" 38 #include "pedigree/kernel/utilities/String.h" 39 #include "pedigree/kernel/utilities/Vector.h" 40 #include "pedigree/kernel/utilities/utility.h" 43 #pragma GCC diagnostic ignored "-Wunreachable-code" 46 extern "C" void vbeModeChangedCallback(
char *pId,
char *pModeId);
48 #define REALMODE_PTR(x) ((x[1] << 4) + x[0]) 51 static size_t g_nDisplays = 0;
58 unsigned char capabilities[4];
59 unsigned short videomodes[2];
69 short segmentA, segmentB;
70 unsigned short realFctPtr[2];
73 unsigned short Xres, Yres;
74 unsigned char Wchar, Ychar, planes, bpp, banks;
75 uint8_t memory_model, bank_size, image_pages;
78 char red_mask, red_position;
79 char green_mask, green_position;
80 char blue_mask, blue_position;
81 char rsv_mask, rsv_position;
82 char directcolor_attributes;
85 unsigned int framebuffer;
86 unsigned int offscreen;
97 virtual void hwRedraw(
98 size_t x = ~0UL,
size_t y = ~0UL,
size_t w = ~0UL,
size_t h = ~0UL);
99 virtual void setFramebuffer(uintptr_t p);
104 size_t m_nBackbufferBytes;
111 extern "C" void vbeModeChangedCallback(
char *pId,
char *pModeId)
113 size_t id = StringToUnsignedLong(pId, 0, 10);
114 size_t mode_id = StringToUnsignedLong(pModeId, 0, 10);
116 if (
id >= g_nDisplays)
119 if (g_pDisplays[
id]->getModeId() != mode_id)
128 NOTICE(
"Not starting VBE module, NOGFX is defined.");
140 QuadWordSet(info, 0, 256 / 8);
141 QuadWordSet(mode, 0, 256 / 8);
142 StringCopyN(info->signature,
"VBE2", 4);
146 static_cast<uint16_t>(reinterpret_cast<uintptr_t>(info) & 0xFFFF));
153 NOTICE(
"abcd: " <<
Hex << ax <<
", " << bx <<
", " << cx <<
", " << dx);
164 if (ax != 0x004F || StringCompareN(info->signature,
"VESA", 4) != 0)
167 "VBE: VESA not supported (ax=" <<
Hex << ax <<
", signature=" 168 << info->signature <<
")!");
169 NOTICE(
"abcd: " <<
Hex << ax <<
", " << bx <<
", " << cx <<
", " << dx);
177 switch (info->version)
180 vbeVersion = VbeDisplay::Vbe1_2;
183 vbeVersion = VbeDisplay::Vbe2_0;
186 vbeVersion = VbeDisplay::Vbe3_0;
189 ERROR(
"VBE: Unrecognised VESA version: " <<
Hex << info->version);
196 size_t maxHeight = 0;
199 size_t maxTextWidth = 0;
200 size_t maxTextHeight = 0;
202 uintptr_t fbAddr = 0;
204 reinterpret_cast<uint16_t *
>(REALMODE_PTR(info->videomodes));
205 for (
int i = 0; modes[i] != 0xFFFF; i++)
211 static_cast<uint16_t>(reinterpret_cast<uintptr_t>(mode) & 0xFFFF));
219 "Testing for mode " <<
Hex << modes[i] <<
" failed, ax=" << ax);
224 bool isGraphicsMode = mode->attributes & 0x10;
225 bool hasLFB = mode->attributes & 0x80;
235 else if (mode->memory_model != 4 && mode->memory_model != 6)
244 pSm->width = mode->Xres;
245 pSm->height = mode->Yres;
247 pSm->framebuffer = mode->framebuffer;
248 pSm->textMode = !isGraphicsMode;
249 fbAddr = mode->framebuffer;
250 pSm->pf.
mRed = mode->red_mask;
251 pSm->pf.
pRed = mode->red_position;
252 pSm->pf.
mGreen = mode->green_mask;
253 pSm->pf.
pGreen = mode->green_position;
254 pSm->pf.
mBlue = mode->blue_mask;
255 pSm->pf.
pBlue = mode->blue_position;
256 pSm->pf.
nBpp = mode->bpp;
257 pSm->pf.
nPitch = mode->pitch;
262 if (mode->Xres > maxWidth)
263 maxWidth = mode->Xres;
264 if (mode->Yres > maxHeight)
265 maxHeight = mode->Yres;
269 if (mode->Xres > maxTextWidth)
270 maxTextWidth = mode->Xres;
271 if (mode->Yres > maxTextHeight)
272 maxTextHeight = mode->Yres;
274 if (mode->bpp > maxBpp)
279 size_t totalMemory = info->totalMemory * 64 * 1024;
284 NOTICE(
"VBE: Detected compatible display modes:");
287 it != modeList.
end(); it++)
291 Hex << pSm->id <<
"\t " <<
Dec << pSm->width <<
"x" << pSm->height
292 <<
"x" << pSm->pf.
nBpp <<
"\t " <<
Hex << pSm->framebuffer);
296 " " << pSm->pf.
mRed <<
"<<" << pSm->pf.
pRed <<
" " 305 NOTICE(
"VBE: End of compatible display modes.");
310 auto searchNode = [&pDevice, fbAddr](
Device *pDev) {
315 for (
unsigned int j = 0; j < pDev->addresses().count(); j++)
317 if (pDev->getPciClassCode() == 0x03 &&
318 pDev->addresses()[j]->m_Address <= fbAddr &&
319 (pDev->addresses()[j]->m_Address +
320 pDev->addresses()[j]->m_Size) > fbAddr)
329 auto f = pedigree_std::make_callable(searchNode);
334 "VBE: Device mapped to framebuffer address '" <<
Hex << fbAddr
341 new VbeDisplay(pDevice, vbeVersion, modeList, totalMemory, g_nDisplays);
343 g_pDisplays[g_nDisplays] = pDisplay;
346 bool bDelayedInsert =
false;
350 "SELECT * FROM displays WHERE pointer=%d",
351 reinterpret_cast<uintptr_t>(pDisplay));
355 ERROR(
"vbe: Got no result when selecting displays");
359 mode_id = pResult->
getNum(0,
"mode_id");
362 "UPDATE displays SET id=%d WHERE pointer=%d", g_nDisplays,
363 reinterpret_cast<uintptr_t>(pDisplay));
364 pResult = Config::instance().
query(str);
373 "Multiple displays for pointer `" 374 << reinterpret_cast<uintptr_t>(pDisplay) <<
"'");
379 bDelayedInsert =
true;
390 pDisplay->setLogicalFramebuffer(pFramebuffer);
394 pProvider->pDisplay = pDisplay;
395 pProvider->pFramebuffer = pFramebuffer;
396 pProvider->maxWidth = maxWidth;
397 pProvider->maxHeight = maxHeight;
398 pProvider->maxTextWidth = maxTextWidth;
399 pProvider->maxTextHeight = maxTextHeight;
400 pProvider->maxDepth = maxBpp;
401 pProvider->bHardwareAccel =
false;
426 MODULE_INFO(
"vbe", &entry, &exit,
"pci",
"config");
428 VbeFramebuffer::VbeFramebuffer()
429 :
Framebuffer(), m_pDisplay(0), m_pBackbuffer(0), m_nBackbufferBytes(0),
430 m_pFramebufferRegion(0), m_Mode()
434 VbeFramebuffer::VbeFramebuffer(
Display *pDisplay)
435 :
Framebuffer(), m_pDisplay(pDisplay), m_pBackbuffer(0),
436 m_nBackbufferBytes(0), m_pFramebufferRegion(0), m_Mode()
451 if (x == 0 && y == 0 && w >= m_Mode.width && h >= m_Mode.height)
455 m_pDisplay->getFramebuffer(), m_pBackbuffer, m_nBackbufferBytes);
460 size_t bytesPerRow = w * m_Mode.bytesPerPixel;
461 size_t xOffset = x * m_Mode.bytesPerPixel;
462 size_t yOffset = y * m_Mode.bytesPerLine;
464 void *firstRowTarget =
465 adjust_pointer(m_pDisplay->getFramebuffer(), yOffset + xOffset);
466 void *firstRowBackbuffer = adjust_pointer(m_pBackbuffer, yOffset + xOffset);
467 for (
size_t yy = 0; yy < h; ++yy)
470 adjust_pointer(firstRowTarget, yy * m_Mode.bytesPerLine);
471 void *backbufferRow =
472 adjust_pointer(firstRowBackbuffer, yy * m_Mode.bytesPerLine);
473 MemoryCopy(targetRow, backbufferRow, bytesPerRow);
477 VbeFramebuffer::~VbeFramebuffer()
481 void VbeFramebuffer::setFramebuffer(uintptr_t p)
484 if (!m_pDisplay->getCurrentScreenMode(m_Mode))
486 ERROR(
"VBE: setting screen mode failed.");
489 m_nBackbufferBytes = m_Mode.bytesPerLine * m_Mode.height;
490 if (m_nBackbufferBytes)
494 if (m_pFramebufferRegion)
496 delete m_pFramebufferRegion;
499 size_t nPages = (m_nBackbufferBytes +
503 m_pFramebufferRegion =
new MemoryRegion(
"VBE Backbuffer");
505 *m_pFramebufferRegion, nPages,
508 delete m_pFramebufferRegion;
509 m_pFramebufferRegion = 0;
514 "VBE backbuffer is at " << reinterpret_cast<uintptr_t>(
515 m_pFramebufferRegion->virtualAddress()));
516 m_pBackbuffer =
reinterpret_cast<char *
>(
517 m_pFramebufferRegion->virtualAddress());
520 Framebuffer::setFramebuffer(reinterpret_cast<uintptr_t>(m_pBackbuffer));
void pushBack(const T &value)
static size_t getPageSize() PURE
size_t rows()
Returns the number of rows.
static PhysicalMemoryManager & instance()
static const size_t continuous
virtual bool setScreenMode(Display::ScreenMode sm)
void executeInterrupt(int interrupt)
virtual bool provides(Type service)
void replaceChild(Device *src, Device *dest)
virtual void hwRedraw(size_t x=~0UL, size_t y=~0UL, size_t w=~0UL, size_t h=~0UL)
Inherited by drivers that provide a hardware redraw function.
static const size_t Write
size_t getNum(size_t row, size_t col)
Returns the value in column 'col' of the result, in number form.
Result * query(const char *sql)
Special memory entity in the kernel's virtual address space.
bool succeeded()
Returns true if the result is valid, false if there was an error.
Abstracts the system's framebuffer offering.
void setParent(Device *p)
static void foreach(Callback callback, Device *root=0)
Service * getService(const String &serviceName)
virtual bool serve(ServiceFeatures::Type type, void *pData, size_t dataLen)=0
std::string errorMessage(size_t buffSz=256)
Returns the error message.
ServiceFeatures * enumerateOperations(const String &serviceName)
Device * getParent() const