wip prep commit in lieu of gfx subsystem update changes, part 2.
[AROS.git] / rom / hidds / vesagfx / vesagfx_support.c
blob0ab159828a8b73dc3f25975a09c28be71d160b21
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: VESA Gfx hardware support functions
6 Lang: English
7 */
9 #define DEBUG 0
11 #include <aros/asmcall.h>
12 #include <aros/debug.h>
13 #include <aros/macros.h>
14 #include <aros/bootloader.h>
15 #include <asm/io.h>
16 #include <proto/bootloader.h>
17 #include <proto/exec.h>
18 #include <proto/oop.h>
19 #include <utility/hooks.h>
20 #include <utility/tagitem.h>
21 #include <oop/oop.h>
22 #include <hidd/pci.h>
24 #include "vesagfx_intern.h"
25 #include "vesagfx_hidd.h"
27 #include <string.h>
29 static void Find_PCI_Card(struct HWData *sd);
31 BOOL initVesaGfxHW(struct HWData *data)
33 struct BootLoaderBase *BootLoaderBase;
34 struct VesaInfo *vi;
36 if ((BootLoaderBase = OpenResource("bootloader.resource")))
38 D(bug("[Vesa] Init: Bootloader.resource opened\n"));
40 if ((vi = (struct VesaInfo *)GetBootInfo(BL_Video)))
42 D(bug("[Vesa] Init: Got Vesa structure from resource\n"));
43 if (vi->ModeNumber == 3)
45 D(bug("[Vesa] Init: Textmode was specified. Aborting\n"));
46 return FALSE;
49 data->width = vi->XSize; data->height = vi->YSize;
50 data->bitsperpixel = data->depth = vi->BitsPerPixel;
51 data->bytesperline = vi->BytesPerLine;
52 data->redmask = vi->Masks[VI_Red];
53 data->greenmask = vi->Masks[VI_Green];
54 data->bluemask = vi->Masks[VI_Blue];
55 data->redshift = vi->Shifts[VI_Red];
56 data->greenshift = vi->Shifts[VI_Green];
57 data->blueshift = vi->Shifts[VI_Blue];
58 data->framebuffer = vi->FrameBuffer;
59 data->palettewidth = vi->PaletteWidth;
61 if (!data->framebuffer)
62 Find_PCI_Card(data);
63 if (!data->framebuffer) {
64 D(bug("[Vesa] HwInit: Framebuffer not found\n"));
65 return FALSE;
68 if (data->depth > 24)
70 data->bytesperpixel = 4;
72 else if (data->depth > 16)
74 data->bytesperpixel = 3;
76 else if (data->depth > 8)
78 data->bytesperpixel = 2;
80 else
82 data->bytesperpixel = 1;
84 D(bug("[Vesa] HwInit: Clearing %d kB of framebuffer at 0x%08x"
85 " size %d kB\n", data->height * data->bytesperline >> 10,
86 data->framebuffer, vi->FrameBufferSize));
87 ClearBuffer(data);
88 D(bug("[Vesa] HwInit: Linear framebuffer at 0x%08x\n",data->framebuffer));
89 D(bug("[Vesa] HwInit: Screenmode %dx%dx%d\n",data->width,data->height,data->depth));
90 D(bug("[Vesa] HwInit: Masks R %08x<<%2d G %08x<<%2d B %08x<<%2d\n",
91 data->redmask, data->redshift,
92 data->greenmask, data->greenshift,
93 data->bluemask, data->blueshift));
94 D(bug("[Vesa] HwInit: PaletteWidth %d\n", data->palettewidth));
95 D(bug("[vesa] HwInit: BytesPerPixel %d\n", data->bytesperpixel));
96 return TRUE;
101 bug("[Vesa] HwInit: No Vesa information from the bootloader. Failing\n");
102 return FALSE;
105 void vesaDoRefreshArea(struct HWData *hwdata, struct VESAGfxBitMapData *data,
106 LONG x1, LONG y1, LONG x2, LONG y2)
108 UBYTE *src, *dst;
109 ULONG srcmod, dstmod;
110 LONG y, w, h, sx, sy;
112 x1 += data->xoffset;
113 y1 += data->yoffset;
114 x2 += data->xoffset;
115 y2 += data->yoffset;
117 /* Clip the rectangle against physical display borders */
118 if ((x1 >= data->disp_width) || (x2 < 1) ||
119 (y1 >= data->disp_height) || (y2 < 1))
120 return;
121 if (x1 < 0)
122 x1 = 0;
123 if (y1 < 0)
124 y1 = 0;
125 if (x2 > data->disp_width)
126 x2 = data->disp_width;
127 if (y2 > data->disp_height)
128 y2 = data->disp_height;
130 /* Calculate width and height */
131 w = x2 - x1;
132 h = y2 - y1;
134 /* Jump back to bitmap coordinates (adjusted) */
135 sx = x1 - data->xoffset;
136 sy = y1 - data->yoffset;
138 w *= data->bytesperpix;
140 srcmod = data->bytesperline;
141 dstmod = hwdata->bytesperline;
143 src = data->VideoData + sy * data->bytesperline + sx * data->bytesperpix;
144 dst = hwdata->framebuffer + y1 * hwdata->bytesperline + x1 * hwdata->bytesperpixel;
147 * Disable screen debug output if not done yet.
148 * TODO: develop some mechanism to tell kernel that we actually
149 * didn't change the mode, so upon warm reboot it can reuse
150 * the framebuffer for debug output.
152 if (!hwdata->owned)
154 RawPutChar(0x03);
155 hwdata->owned = TRUE;
159 ** common sense assumption: memcpy can't possibly be faster than CopyMem[Quick]
161 if ((srcmod != dstmod) || (srcmod != w))
163 for(y = 0; y < h; y++)
165 CopyMem(src, dst, w);
166 src += srcmod;
167 dst += dstmod;
170 else
172 /* this is a plain total fast rulez copy */
173 CopyMem(src, dst, w*h);
177 AROS_UFH3(void, Enumerator,
178 AROS_UFHA(struct Hook *, hook, A0),
179 AROS_UFHA(OOP_Object *, pciDevice, A2),
180 AROS_UFHA(APTR, message, A1))
182 AROS_USERFUNC_INIT
184 APTR buf;
185 IPTR size;
186 IPTR Vendor;
187 OOP_Object *driver;
188 struct pHidd_PCIDriver_MapPCI mappci,*msg = &mappci;
189 struct HWData *sd = hook->h_Data;
191 D(bug("[VESAGfx] Enumerator: Found device\n"));
193 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (APTR)&driver);
194 OOP_GetAttr(pciDevice, aHidd_PCIDevice_VendorID, &Vendor);
195 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0, (APTR)&buf);
196 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0, &size);
198 /* BIOS of S3 video cards may forget to set up linear framebuffer start address.
199 Here we do this manually.
200 This thing was looked up in x.org S3 driver source code. Applicable to all S3 cards. */
201 if (Vendor == PCI_VENDOR_S3) {
202 outb(0x59, vgaIOBase + 4);
203 outb((IPTR)buf >> 24, vgaIOBase + 5);
204 outb(0x5A, vgaIOBase + 4);
205 outb((IPTR)buf >> 16, vgaIOBase + 5);
208 mappci.mID = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_MapPCI);
209 mappci.PCIAddress = buf;
210 mappci.Length = size;
211 sd->framebuffer = (APTR)OOP_DoMethod(driver, (OOP_Msg)msg);
213 D(bug("[VESAGfx] Got framebuffer @ %x (size=%x)\n", sd->framebuffer, size));
215 AROS_USERFUNC_EXIT
218 static void Find_PCI_Card(struct HWData *sd)
220 OOP_Object *pci;
222 D(bug("[VESAGfx] Find_PCI_Card\n"));
224 sd->pciDeviceAttrBase = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
225 if (sd->pciDeviceAttrBase)
227 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
229 D(bug("[VESAGfx] Creating PCI object\n"));
231 if (pci)
233 struct Hook FindHook = {
234 h_Entry: (IPTR (*)())Enumerator,
235 h_Data: sd,
238 struct TagItem Requirements[] = {
239 { tHidd_PCI_Interface, 0x00 },
240 { tHidd_PCI_Class, 0x03 },
241 { tHidd_PCI_SubClass, 0x00 },
242 { TAG_DONE, 0UL }
245 struct pHidd_PCI_EnumDevices enummsg = {
246 mID: OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_EnumDevices),
247 callback: &FindHook,
248 requirements: (struct TagItem*)&Requirements,
249 }, *msg = &enummsg;
250 D(bug("[VESAGfx] Calling search Hook\n"));
251 OOP_DoMethod(pci, (OOP_Msg)msg);
252 OOP_DisposeObject(pci);
255 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
260 ** DACLoad --
261 ** load a palette
263 void DACLoad(struct VESAGfx_staticdata *xsd, UBYTE *DAC,
264 unsigned char first, int num)
266 int i, n;
268 n = first * 3;
270 ObtainSemaphore(&xsd->HW_acc);
271 outb(first, 0x3C8);
272 for (i=0; i<num*3; i++)
274 outb(DAC[n++], 0x3C9);
276 ReleaseSemaphore(&xsd->HW_acc);
280 ** ClearBuffer --
281 ** clear the screen buffer
283 void ClearBuffer(struct HWData *data)
285 IPTR *p, *limit;
287 if (!data->owned)
289 RawPutChar(0x03);
290 data->owned = TRUE;
293 p = (IPTR *)data->framebuffer;
294 limit = (IPTR *)((IPTR)p + data->height * data->bytesperline);
295 while (p < limit)
296 *p++ = 0;