c55cd929b00770d9483021b985fc17a2bb31707a
[tpg/acess2.git] / Kernel / drvutil.c
1 /*
2  * Acess2
3  * Common Driver/Filesystem Helper Functions
4  */
5 #define DEBUG   0
6 #include <acess.h>
7 #include <api_drv_disk.h>
8 #include <api_drv_video.h>
9
10 // === TYPES ===
11
12 // === PROTOTYPES ===
13 //int   DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers);
14 //size_t        DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Src);
15 void    DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
16 void    DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);
17
18 // === GLOBALS ===
19 tDrvUtil_Video_2DHandlers       gDrvUtil_Stub_2DFunctions = {
20         NULL,
21         DrvUtil_Video_2D_Fill,
22         DrvUtil_Video_2D_Blit
23 };
24
25 // === CODE ===
26 // --- Video Driver Helpers ---
27 int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
28         tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers)
29 {
30         void    *stream = Buffer;
31          int    rem = Length;
32          int    op;
33         while( rem )
34         {
35                 rem --;
36                 op = *(Uint8*)stream;
37                 stream = (void*)((tVAddr)stream + 1);
38                 
39                 if(op > NUM_VIDEO_2DOPS) {
40                         Log_Warning("DrvUtil",
41                                 "DrvUtil_Video_2DStream: Unknown operation %i",
42                                 op);
43                         return Length-rem;
44                 }
45                 
46                 if(op*sizeof(void*) > SizeofHandlers) {
47                         Log_Warning("DrvUtil",
48                                 "DrvUtil_Video_2DStream: Driver does not support op %i",
49                                 op);
50                         return Length-rem;
51                 }
52                 
53                 switch(op)
54                 {
55                 case VIDEO_2DOP_NOP:    break;
56                 
57                 case VIDEO_2DOP_FILL:
58                         if(rem < 12)    return Length-rem;
59                         
60                         if(!Handlers->Fill) {
61                                 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
62                                         " does not support VIDEO_2DOP_FILL");
63                                 return Length-rem;
64                         }
65                         
66                         Handlers->Fill(
67                                 Ent,
68                                 ((Uint16*)stream)[0], ((Uint16*)stream)[1],
69                                 ((Uint16*)stream)[2], ((Uint16*)stream)[3],
70                                 ((Uint32*)stream)[2]
71                                 );
72                         
73                         rem -= 12;
74                         stream = (void*)((tVAddr)stream + 12);
75                         break;
76                 
77                 case VIDEO_2DOP_BLIT:
78                         if(rem < 12)    return Length-rem;
79                         
80                         if(!Handlers->Blit) {
81                                 Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
82                                         " does not support VIDEO_2DOP_BLIT");
83                                 return Length-rem;
84                         }
85                         
86                         Handlers->Blit(
87                                 Ent,
88                                 ((Uint16*)stream)[0], ((Uint16*)stream)[1],
89                                 ((Uint16*)stream)[2], ((Uint16*)stream)[3],
90                                 ((Uint16*)stream)[4], ((Uint16*)stream)[5]
91                                 );
92                         
93                         rem -= 12;
94                         stream = (void*)((tVAddr)stream + 12);
95                         break;
96                 
97                 }
98         }
99         return 0;
100 }
101
102 int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Buffer)
103 {
104         Uint8   *dest;
105         ENTER("iMode pFBInfo xOffset xLength pBuffer",
106                 Mode, FBInfo, Offset, Length, Buffer);
107         switch( Mode )
108         {
109         case VIDEO_BUFFMT_TEXT:
110                 {
111                 tVT_Char        *chars = Buffer;
112                  int    bytes_per_px = (FBInfo->Depth + 7) / 8;
113                  int    widthInChars = FBInfo->Width/giVT_CharWidth;
114                  int    heightInChars = FBInfo->Height/giVT_CharHeight;
115                  int    x, y, i;
116         
117                 LOG("bytes_per_px = %i", bytes_per_px);
118                 LOG("widthInChars = %i, heightInChars = %i", widthInChars, heightInChars);
119         
120                 Length /= sizeof(tVT_Char);     Offset /= sizeof(tVT_Char);
121                 
122                 x = Offset % widthInChars;      y = Offset / widthInChars;
123                 LOG("x = %i, y = %i", x, y);    
124         
125                 // Sanity Check
126                 if(Offset > heightInChars * widthInChars)       LEAVE_RET('i', 0);
127                 if(y >= heightInChars)  LEAVE_RET('i', 0);
128                 
129                 if( Offset + Length > heightInChars*widthInChars )
130                 {
131                         Length = heightInChars*widthInChars - Offset;
132                 }
133                 
134                 dest = FBInfo->Framebuffer;
135                 LOG("dest = %p", dest);
136                 dest += y * giVT_CharHeight * FBInfo->Pitch;
137                 LOG("dest = %p", dest);
138                 
139                 for( i = 0; i < Length; i++ )
140                 {
141                         if( y >= heightInChars )
142                         {
143                                 Log_Notice("DrvUtil", "Stopped at %i", i);
144                                 break;
145                         }
146
147 //                      LOG("chars->Ch=0x%x,chars->BGCol=0x%x,chars->FGCol=0x%x",
148 //                              chars->Ch, chars->BGCol, chars->FGCol);         
149
150                         VT_Font_Render(
151                                 chars->Ch,
152                                 dest + x*giVT_CharWidth*bytes_per_px, FBInfo->Depth, FBInfo->Pitch,
153                                 VT_Colour12toN(chars->BGCol, FBInfo->Depth),
154                                 VT_Colour12toN(chars->FGCol, FBInfo->Depth)
155                                 );
156                         
157                         chars ++;
158                         x ++;
159                         if( x >= widthInChars )
160                         {
161                                 x = 0;
162                                 y ++;
163                                 dest += FBInfo->Pitch*giVT_CharHeight;
164                                 LOG("dest = %p", dest);
165                         }
166                 }
167                 Length = i * sizeof(tVT_Char);
168                 }
169                 break;
170         
171         case VIDEO_BUFFMT_FRAMEBUFFER:
172                 if(FBInfo->Width*FBInfo->Height*4 < Offset+Length)
173                 {
174                         Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Framebuffer Overflow");
175                         return 0;
176                 }
177                 
178                 //TODO: Handle non 32-bpp framebuffer modes
179                 if( FBInfo->Depth != 32 ) {
180                         Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Don't support non 32-bpp FB mode");
181                         return 0;
182                 }       
183
184                 
185                 //TODO: Handle pitch != Width*BytesPerPixel
186                 // Copy to Frambuffer
187                 dest = (Uint8 *)FBInfo->Framebuffer + Offset;
188                 memcpy(dest, Buffer, Length);
189                 break;
190         
191         case VIDEO_BUFFMT_2DSTREAM:
192                 Length = DrvUtil_Video_2DStream(
193                         FBInfo, Buffer, Length,
194                         &gDrvUtil_Stub_2DFunctions, sizeof(gDrvUtil_Stub_2DFunctions)
195                         );
196                 break;
197         
198         default:
199                 LEAVE('i', -1);
200                 return -1;
201         }
202         LEAVE('x', Length);
203         return Length;
204 }
205
206 void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)
207 {
208         tDrvUtil_Video_BufInfo  *FBInfo = Ent;
209
210         // TODO: Handle non-32bit modes
211         if( FBInfo->Depth != 32 )       return;
212
213         // TODO: Be less hacky
214          int    pitch = FBInfo->Pitch/4;
215         Uint32  *buf = (Uint32*)FBInfo->Framebuffer + Y*pitch + X;
216         while( H -- ) {
217                 Uint32 *tmp;
218                  int    i;
219                 tmp = buf;
220                 for(i=W;i--;tmp++)      *tmp = Colour;
221                 buf += pitch;
222         }
223 }
224
225 void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)
226 {
227         tDrvUtil_Video_BufInfo  *FBInfo = Ent;
228          int    scrnpitch = FBInfo->Pitch;
229          int    bytes_per_px = (FBInfo->Depth + 7) / 8;
230          int    dst = DstY*scrnpitch + DstX;
231          int    src = SrcY*scrnpitch + SrcX;
232          int    tmp;
233         
234         //Log("Vesa_2D_Blit: (Ent=%p, DstX=%i, DstY=%i, SrcX=%i, SrcY=%i, W=%i, H=%i)",
235         //      Ent, DstX, DstY, SrcX, SrcY, W, H);
236         
237         if(SrcX + W > FBInfo->Width)    W = FBInfo->Width - SrcX;
238         if(DstX + W > FBInfo->Width)    W = FBInfo->Width - DstX;
239         if(SrcY + H > FBInfo->Height)   H = FBInfo->Height - SrcY;
240         if(DstY + H > FBInfo->Height)   H = FBInfo->Height - DstY;
241         
242         //Debug("W = %i, H = %i", W, H);
243         
244         if( dst > src ) {
245                 // Reverse copy
246                 dst += H*scrnpitch;
247                 src += H*scrnpitch;
248                 while( H -- ) {
249                         dst -= scrnpitch;
250                         src -= scrnpitch;
251                         tmp = W*bytes_per_px;
252                         for( tmp = W; tmp --; ) {
253                                 *((Uint8*)FBInfo->Framebuffer + dst + tmp) = *((Uint8*)FBInfo->Framebuffer + src + tmp);
254                         }
255                 }
256         }
257         else {
258                 // Normal copy is OK
259                 while( H -- ) {
260                         memcpy((Uint8*)FBInfo->Framebuffer + dst, (Uint8*)FBInfo->Framebuffer + src, W*bytes_per_px);
261                         dst += scrnpitch;
262                         src += scrnpitch;
263                 }
264         }
265         //Log("Vesa_2D_Blit: RETURN");
266 }
267         
268
269 // --- Disk Driver Helpers ---
270 Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
271         tDrvUtil_Callback ReadBlocks, Uint64 BlockSize, Uint Argument)
272 {
273         Uint8   tmp[BlockSize]; // C99
274         Uint64  block = Start / BlockSize;
275          int    offset = Start - block * BlockSize;
276          int    leading = BlockSize - offset;
277         Uint64  num;
278          int    tailings;
279         Uint64  ret;
280         
281         ENTER("XStart XLength pBuffer pReadBlocks XBlockSize xArgument",
282                 Start, Length, Buffer, ReadBlocks, BlockSize, Argument);
283         
284         // Non aligned start, let's fix that!
285         if(offset != 0)
286         {
287                 if(leading > Length)    leading = Length;
288                 LOG("Reading %i bytes from Block1+%i", leading, offset);
289                 ret = ReadBlocks(block, 1, tmp, Argument);
290                 if(ret != 1) {
291                         LEAVE('i', 0);
292                         return 0;
293                 }
294                 memcpy( Buffer, &tmp[offset], leading );
295                 
296                 if(leading == Length) {
297                         LEAVE('i', leading);
298                         return leading;
299                 }
300                 
301                 Buffer = (Uint8*)Buffer + leading;
302                 block ++;
303                 num = ( Length - leading ) / BlockSize;
304                 tailings = Length - num * BlockSize - leading;
305         }
306         else {
307                 num = Length / BlockSize;
308                 tailings = Length % BlockSize;
309         }
310         
311         // Read central blocks
312         if(num)
313         {
314                 LOG("Reading %i blocks", num);
315                 ret = ReadBlocks(block, num, Buffer, Argument);
316                 if(ret != num ) {
317                         LEAVE('X', leading + ret * BlockSize);
318                         return leading + ret * BlockSize;
319                 }
320         }
321         
322         // Read last tailing block
323         if(tailings != 0)
324         {
325                 LOG("Reading %i bytes from last block", tailings);
326                 block += num;
327                 Buffer = (Uint8*)Buffer + num * BlockSize;
328                 ret = ReadBlocks(block, 1, tmp, Argument);
329                 if(ret != 1) {
330                         LEAVE('X', leading + num * BlockSize);
331                         return leading + num * BlockSize;
332                 }
333                 memcpy( Buffer, tmp, tailings );
334         }
335         
336         LEAVE('X', Length);
337         return Length;
338 }
339
340 Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, void *Buffer,
341         tDrvUtil_Callback ReadBlocks, tDrvUtil_Callback WriteBlocks,
342         Uint64 BlockSize, Uint Argument)
343 {
344         Uint8   tmp[BlockSize]; // C99
345         Uint64  block = Start / BlockSize;
346          int    offset = Start - block * BlockSize;
347          int    leading = BlockSize - offset;
348         Uint64  num;
349          int    tailings;
350         Uint64  ret;
351         
352         ENTER("XStart XLength pBuffer pReadBlocks pWriteBlocks XBlockSize xArgument",
353                 Start, Length, Buffer, ReadBlocks, WriteBlocks, BlockSize, Argument);
354         
355         // Non aligned start, let's fix that!
356         if(offset != 0)
357         {
358                 if(leading > Length)    leading = Length;
359                 LOG("Writing %i bytes to Block1+%i", leading, offset);
360                 // Read a copy of the block
361                 ret = ReadBlocks(block, 1, tmp, Argument);
362                 if(ret != 1) {
363                         LEAVE('i', 0);
364                         return 0;
365                 }
366                 // Modify
367                 memcpy( &tmp[offset], Buffer, leading );
368                 // Write Back
369                 ret = WriteBlocks(block, 1, tmp, Argument);
370                 if(ret != 1) {
371                         LEAVE('i', 0);
372                         return 0;
373                 }
374                 
375                 if(leading == Length) {
376                         LEAVE('i', leading);
377                         return leading;
378                 }
379                 
380                 Buffer = (Uint8*)Buffer + leading;
381                 block ++;
382                 num = ( Length - leading ) / BlockSize;
383                 tailings = Length - num * BlockSize - leading;
384         }
385         else {
386                 num = Length / BlockSize;
387                 tailings = Length % BlockSize;
388         }
389         
390         // Read central blocks
391         if(num)
392         {
393                 LOG("Writing %i blocks", num);
394                 ret = WriteBlocks(block, num, Buffer, Argument);
395                 if(ret != num ) {
396                         LEAVE('X', leading + ret * BlockSize);
397                         return leading + ret * BlockSize;
398                 }
399         }
400         
401         // Read last tailing block
402         if(tailings != 0)
403         {
404                 LOG("Writing %i bytes to last block", tailings);
405                 block += num;
406                 Buffer = (Uint8*)Buffer + num * BlockSize;
407                 // Read
408                 ret = ReadBlocks(block, 1, tmp, Argument);
409                 if(ret != 1) {
410                         LEAVE('X', leading + num * BlockSize);
411                         return leading + num * BlockSize;
412                 }
413                 // Modify
414                 memcpy( tmp, Buffer, tailings );
415                 // Write
416                 ret = WriteBlocks(block, 1, tmp, Argument);
417                 if(ret != 1) {
418                         LEAVE('X', leading + num * BlockSize);
419                         return leading + num * BlockSize;
420                 }
421                 
422         }
423         
424         LEAVE('X', Length);
425         return Length;
426 }

UCC git Repository :: git.ucc.asn.au