Removed cut-and-pasted code for clamping of X/Y offsets. These
[AROS.git] / rom / hidds / vesa / hardware.c
blob5ec639e980c0f560c963030ef152d138a72e56d8
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: vesa "hardware" 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 "bitmap.h"
25 #include "vesagfxclass.h"
26 #include "hardware.h"
28 #include <string.h>
30 static void Find_PCI_Card(struct HWData *sd);
32 BOOL initVesaGfxHW(struct HWData *data)
34 struct BootLoaderBase *BootLoaderBase;
35 struct VesaInfo *vi;
37 if ((BootLoaderBase = OpenResource("bootloader.resource")))
39 D(bug("[Vesa] Init: Bootloader.resource opened\n"));
41 if ((vi = (struct VesaInfo *)GetBootInfo(BL_Video)))
43 D(bug("[Vesa] Init: Got Vesa structure from resource\n"));
44 if (vi->ModeNumber == 3)
46 D(bug("[Vesa] Init: Textmode was specified. Aborting\n"));
47 return FALSE;
50 data->width = vi->XSize; data->height = vi->YSize;
51 data->bitsperpixel = data->depth = vi->BitsPerPixel;
52 data->bytesperline = vi->BytesPerLine;
53 data->redmask = vi->Masks[VI_Red];
54 data->greenmask = vi->Masks[VI_Green];
55 data->bluemask = vi->Masks[VI_Blue];
56 data->redshift = vi->Shifts[VI_Red];
57 data->greenshift = vi->Shifts[VI_Green];
58 data->blueshift = vi->Shifts[VI_Blue];
59 data->framebuffer = vi->FrameBuffer;
60 data->palettewidth = vi->PaletteWidth;
62 if (!data->framebuffer)
63 Find_PCI_Card(data);
64 if (!data->framebuffer) {
65 D(bug("[Vesa] HwInit: Framebuffer not found\n"));
66 return FALSE;
69 if (data->depth > 24)
71 data->bytesperpixel = 4;
73 else if (data->depth > 16)
75 data->bytesperpixel = 3;
77 else if (data->depth > 8)
79 data->bytesperpixel = 2;
81 else
83 data->bytesperpixel = 1;
85 D(bug("[Vesa] HwInit: Clearing %d kB of framebuffer at 0x%08x"
86 " size %d kB\n", data->height * data->bytesperline >> 10,
87 data->framebuffer, vi->FrameBufferSize));
88 ClearBuffer(data);
89 D(bug("[Vesa] HwInit: Linear framebuffer at 0x%08x\n",data->framebuffer));
90 D(bug("[Vesa] HwInit: Screenmode %dx%dx%d\n",data->width,data->height,data->depth));
91 D(bug("[Vesa] HwInit: Masks R %08x<<%2d G %08x<<%2d B %08x<<%2d\n",
92 data->redmask, data->redshift,
93 data->greenmask, data->greenshift,
94 data->bluemask, data->blueshift));
95 D(bug("[Vesa] HwInit: PaletteWidth %d\n", data->palettewidth));
96 D(bug("[vesa] HwInit: BytesPerPixel %d\n", data->bytesperpixel));
97 return TRUE;
102 bug("[Vesa] HwInit: No Vesa information from the bootloader. Failing\n");
103 return FALSE;
106 void vesaDoRefreshArea(struct HWData *hwdata, struct BitmapData *data,
107 LONG x1, LONG y1, LONG x2, LONG y2)
109 UBYTE *src, *dst;
110 ULONG srcmod, dstmod;
111 LONG y, w, h, sx, sy;
113 x1 += data->xoffset;
114 y1 += data->yoffset;
115 x2 += data->xoffset;
116 y2 += data->yoffset;
118 /* Clip the rectangle against physical display borders */
119 if ((x1 >= data->disp_width) || (x2 < 1) ||
120 (y1 >= data->disp_height) || (y2 < 1))
121 return;
122 if (x1 < 0)
123 x1 = 0;
124 if (y1 < 0)
125 y1 = 0;
126 if (x2 > data->disp_width)
127 x2 = data->disp_width;
128 if (y2 > data->disp_height)
129 y2 = data->disp_height;
131 /* Calculate width and height */
132 w = x2 - x1;
133 h = y2 - y1;
135 /* Jump back to bitmap coordinates (adjusted) */
136 sx = x1 - data->xoffset;
137 sy = y1 - data->yoffset;
139 w *= data->bytesperpix;
141 srcmod = data->bytesperline;
142 dstmod = hwdata->bytesperline;
144 src = data->VideoData + sy * data->bytesperline + sx * data->bytesperpix;
145 dst = hwdata->framebuffer + y1 * hwdata->bytesperline + x1 * hwdata->bytesperpixel;
148 * Disable screen debug output if not done yet.
149 * TODO: develop some mechanism to tell kernel that we actually
150 * didn't change the mode, so upon warm reboot it can reuse
151 * the framebuffer for debug output.
153 if (!hwdata->owned)
155 RawPutChar(0x03);
156 hwdata->owned = TRUE;
160 ** common sense assumption: memcpy can't possibly be faster than CopyMem[Quick]
162 if ((srcmod != dstmod) || (srcmod != w))
164 for(y = 0; y < h; y++)
166 CopyMem(src, dst, w);
167 src += srcmod;
168 dst += dstmod;
171 else
173 /* this is a plain total fast rulez copy */
174 CopyMem(src, dst, w*h);
178 AROS_UFH3(void, Enumerator,
179 AROS_UFHA(struct Hook *, hook, A0),
180 AROS_UFHA(OOP_Object *, pciDevice, A2),
181 AROS_UFHA(APTR, message, A1))
183 AROS_USERFUNC_INIT
185 APTR buf;
186 IPTR size;
187 IPTR Vendor;
188 OOP_Object *driver;
189 struct pHidd_PCIDriver_MapPCI mappci,*msg = &mappci;
190 struct HWData *sd = hook->h_Data;
192 D(bug("[VESA] Enumerator: Found device\n"));
194 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Driver, (APTR)&driver);
195 OOP_GetAttr(pciDevice, aHidd_PCIDevice_VendorID, &Vendor);
196 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Base0, (APTR)&buf);
197 OOP_GetAttr(pciDevice, aHidd_PCIDevice_Size0, &size);
199 /* BIOS of S3 video cards may forget to set up linear framebuffer start address.
200 Here we do this manually.
201 This thing was looked up in x.org S3 driver source code. Applicable to all S3 cards. */
202 if (Vendor == PCI_VENDOR_S3) {
203 outb(0x59, vgaIOBase + 4);
204 outb((IPTR)buf >> 24, vgaIOBase + 5);
205 outb(0x5A, vgaIOBase + 4);
206 outb((IPTR)buf >> 16, vgaIOBase + 5);
209 mappci.mID = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_MapPCI);
210 mappci.PCIAddress = buf;
211 mappci.Length = size;
212 sd->framebuffer = (APTR)OOP_DoMethod(driver, (OOP_Msg)msg);
214 D(bug("[VESA] Got framebuffer @ %x (size=%x)\n", sd->framebuffer, size));
216 AROS_USERFUNC_EXIT
219 static void Find_PCI_Card(struct HWData *sd)
221 OOP_Object *pci;
223 D(bug("[VESA] Find_PCI_Card\n"));
225 sd->pciDeviceAttrBase = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
226 if (sd->pciDeviceAttrBase)
228 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
230 D(bug("[VESA] Creating PCI object\n"));
232 if (pci)
234 struct Hook FindHook = {
235 h_Entry: (IPTR (*)())Enumerator,
236 h_Data: sd,
239 struct TagItem Requirements[] = {
240 { tHidd_PCI_Interface, 0x00 },
241 { tHidd_PCI_Class, 0x03 },
242 { tHidd_PCI_SubClass, 0x00 },
243 { TAG_DONE, 0UL }
246 struct pHidd_PCI_EnumDevices enummsg = {
247 mID: OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_EnumDevices),
248 callback: &FindHook,
249 requirements: (struct TagItem*)&Requirements,
250 }, *msg = &enummsg;
251 D(bug("[VESA] Calling search Hook\n"));
252 OOP_DoMethod(pci, (OOP_Msg)msg);
253 OOP_DisposeObject(pci);
256 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
261 ** DACLoad --
262 ** load a palette
264 void DACLoad(struct VesaGfx_staticdata *xsd, UBYTE *DAC,
265 unsigned char first, int num)
267 int i, n;
269 n = first * 3;
271 ObtainSemaphore(&xsd->HW_acc);
272 outb(first, 0x3C8);
273 for (i=0; i<num*3; i++)
275 outb(DAC[n++], 0x3C9);
277 ReleaseSemaphore(&xsd->HW_acc);
281 ** ClearBuffer --
282 ** clear the screen buffer
284 void ClearBuffer(struct HWData *data)
286 IPTR *p, *limit;
288 if (!data->owned)
290 RawPutChar(0x03);
291 data->owned = TRUE;
294 p = (IPTR *)data->framebuffer;
295 limit = (IPTR *)((IPTR)p + data->height * data->bytesperline);
296 while (p < limit)
297 *p++ = 0;