1 /* Author:
2 Rudolf Cornelissen 4/2003-1/2006
3 */
4
5 #define MODULE_BIT 0x00008000
6
7 #include "nm_std.h"
8
9 static status_t test_ram(void);
10 static status_t nmxxxx_general_powerup (void);
11 static status_t nm_general_bios_to_powergraphics(void);
12
nm_dump_configuration_space(void)13 static void nm_dump_configuration_space (void)
14 {
15 #define DUMP_CFG(reg, type) if (si->ps.card_type >= type) do { \
16 uint32 value = CFGR(reg); \
17 MSG(("configuration_space 0x%02x %20s 0x%08x\n", \
18 NMCFG_##reg, #reg, value)); \
19 } while (0)
20 DUMP_CFG (DEVID, 0);
21 DUMP_CFG (DEVCTRL, 0);
22 DUMP_CFG (CLASS, 0);
23 DUMP_CFG (HEADER, 0);
24 DUMP_CFG (BASE1FB, 0);
25 DUMP_CFG (BASE2REG1,0);
26 DUMP_CFG (BASE3REG2,0);
27 DUMP_CFG (BASE4, 0);
28 DUMP_CFG (BASE5, 0);
29 DUMP_CFG (BASE6, 0);
30 DUMP_CFG (BASE7, 0);
31 DUMP_CFG (SUBSYSID1,0);
32 DUMP_CFG (ROMBASE, 0);
33 DUMP_CFG (CAPPTR, 0);
34 DUMP_CFG (CFG_1, 0);
35 DUMP_CFG (INTERRUPT,0);
36 DUMP_CFG (CFG_3, 0);
37 DUMP_CFG (CFG_4, 0);
38 DUMP_CFG (CFG_5, 0);
39 DUMP_CFG (CFG_6, 0);
40 DUMP_CFG (CFG_7, 0);
41 DUMP_CFG (CFG_8, 0);
42 DUMP_CFG (CFG_9, 0);
43 DUMP_CFG (CFG_10, 0);
44 DUMP_CFG (CFG_11, 0);
45 DUMP_CFG (CFG_12, 0);
46 DUMP_CFG (CFG_13, 0);
47 DUMP_CFG (CFG_14, 0);
48 DUMP_CFG (CFG_15, 0);
49 DUMP_CFG (CFG_16, 0);
50 DUMP_CFG (CFG_17, 0);
51 DUMP_CFG (CFG_18, 0);
52 DUMP_CFG (CFG_19, 0);
53 DUMP_CFG (CFG_20, 0);
54 DUMP_CFG (CFG_21, 0);
55 DUMP_CFG (CFG_22, 0);
56 DUMP_CFG (CFG_23, 0);
57 DUMP_CFG (CFG_24, 0);
58 DUMP_CFG (CFG_25, 0);
59 DUMP_CFG (CFG_26, 0);
60 DUMP_CFG (CFG_27, 0);
61 DUMP_CFG (CFG_28, 0);
62 DUMP_CFG (CFG_29, 0);
63 DUMP_CFG (CFG_30, 0);
64 DUMP_CFG (CFG_31, 0);
65 DUMP_CFG (CFG_32, 0);
66 DUMP_CFG (CFG_33, 0);
67 DUMP_CFG (CFG_34, 0);
68 DUMP_CFG (CFG_35, 0);
69 DUMP_CFG (CFG_36, 0);
70 DUMP_CFG (CFG_37, 0);
71 DUMP_CFG (CFG_38, 0);
72 DUMP_CFG (CFG_39, 0);
73 DUMP_CFG (CFG_40, 0);
74 DUMP_CFG (CFG_41, 0);
75 DUMP_CFG (CFG_42, 0);
76 DUMP_CFG (CFG_43, 0);
77 DUMP_CFG (CFG_44, 0);
78 DUMP_CFG (CFG_45, 0);
79 DUMP_CFG (CFG_46, 0);
80 DUMP_CFG (CFG_47, 0);
81 DUMP_CFG (CFG_48, 0);
82 DUMP_CFG (CFG_49, 0);
83 DUMP_CFG (CFG_50, 0);
84 #undef DUMP_CFG
85 }
86
nm_general_powerup()87 status_t nm_general_powerup()
88 {
89 status_t status;
90
91 LOG(1,("POWERUP: Haiku Neomagic Accelerant 0.14 running.\n"));
92
93 /* log VBLANK INT usability status */
94 if (si->ps.int_assigned)
95 LOG(4,("POWERUP: Usable INT assigned to HW; Vblank semaphore enabled\n"));
96 else
97 LOG(4,("POWERUP: No (usable) INT assigned to HW; Vblank semaphore disabled\n"));
98
99 /* WARNING:
100 * _adi.name_ and _adi.chipset_ can contain 31 readable characters max.!!! */
101
102 /* detect card type and power it up */
103 switch(CFGR(DEVID))
104 {
105 case 0x000110c8: //NM2070 ISA
106 si->ps.card_type = NM2070;
107 sprintf(si->adi.name, "Neomagic MagicGraph 128");
108 sprintf(si->adi.chipset, "NM2070 (ISA)");
109 break;
110 case 0x000210c8: //NM2090 ISA
111 si->ps.card_type = NM2090;
112 sprintf(si->adi.name, "Neomagic MagicGraph 128V");
113 sprintf(si->adi.chipset, "NM2090 (ISA)");
114 break;
115 case 0x000310c8: //NM2093 ISA
116 si->ps.card_type = NM2093;
117 sprintf(si->adi.name, "Neomagic MagicGraph 128ZV");
118 sprintf(si->adi.chipset, "NM2093 (ISA)");
119 break;
120 case 0x008310c8: //NM2097 PCI
121 si->ps.card_type = NM2097;
122 sprintf(si->adi.name, "Neomagic MagicGraph 128ZV+");
123 sprintf(si->adi.chipset, "NM2097 (PCI)");
124 break;
125 case 0x000410c8: //NM2160 PCI
126 si->ps.card_type = NM2160;
127 sprintf(si->adi.name, "Neomagic MagicGraph 128XD");
128 sprintf(si->adi.chipset, "NM2160 (PCI)");
129 break;
130 case 0x000510c8: //NM2200
131 si->ps.card_type = NM2200;
132 sprintf(si->adi.name, "Neomagic MagicMedia 256AV");
133 sprintf(si->adi.chipset, "NM2200");
134 break;
135 case 0x002510c8: //NM2230
136 si->ps.card_type = NM2230;
137 sprintf(si->adi.name, "Neomagic MagicMedia 256AV+");
138 sprintf(si->adi.chipset, "NM2230");
139 break;
140 case 0x000610c8: //NM2360
141 si->ps.card_type = NM2360;
142 sprintf(si->adi.name, "Neomagic MagicMedia 256ZX");
143 sprintf(si->adi.chipset, "NM2360");
144 break;
145 case 0x001610c8: //NM2380
146 si->ps.card_type = NM2380;
147 sprintf(si->adi.name, "Neomagic MagicMedia 256XL+");
148 sprintf(si->adi.chipset, "NM2380");
149 break;
150 default:
151 LOG(8,("POWERUP: Failed to detect valid card 0x%08x\n",CFGR(DEVID)));
152 return B_ERROR;
153 }
154
155 /* power up the card */
156 status = nmxxxx_general_powerup();
157
158 /* override memory detection if requested by user */
159 if (si->settings.memory != 0)
160 si->ps.memory_size = si->settings.memory;
161
162 return status;
163 }
164
test_ram(void)165 static status_t test_ram(void)
166 {
167 uint32 value, offset;
168 status_t result = B_OK;
169
170 /* make sure we don't corrupt the hardware cursor by using fbc.frame_buffer. */
171 if (si->fbc.frame_buffer == NULL)
172 {
173 LOG(8,("INIT: test_ram detected NULL pointer.\n"));
174 return B_ERROR;
175 }
176
177 for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
178 {
179 /* write testpattern to cardRAM */
180 ((uint32 *)si->fbc.frame_buffer)[offset] = value;
181 /* toggle testpattern */
182 value = 0xffffffff - value;
183 }
184
185 for (offset = 0, value = 0x55aa55aa; offset < 256; offset++)
186 {
187 /* readback and verify testpattern from cardRAM */
188 if (((uint32 *)si->fbc.frame_buffer)[offset] != value) result = B_ERROR;
189 /* toggle testpattern */
190 value = 0xffffffff - value;
191 }
192 return result;
193 }
194
195 /* NOTE:
196 * This routine *has* to be done *after* SetDispplayMode has been executed,
197 * or test results will not be representative!
198 * (CAS latency is dependant on nm setup on some (DRAM) boards) */
nm_set_cas_latency()199 status_t nm_set_cas_latency()
200 {
201 /* check current RAM access to see if we need to change anything */
202 if (test_ram() == B_OK)
203 {
204 LOG(4,("INIT: RAM access OK.\n"));
205 return B_OK;
206 }
207
208 /* check if we read PINS at starttime so we have valid registersettings at our disposal */
209 LOG(4,("INIT: RAM access errors; not fixable: missing coldstart specs.\n"));
210 return B_ERROR;
211 }
212
nm_unlock()213 void nm_unlock()
214 {
215 /* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
216 ISAGRPHW(GRPHXLOCK, 0x26);
217 }
218
nmxxxx_general_powerup()219 static status_t nmxxxx_general_powerup()
220 {
221 uint8 temp;
222 // status_t result;
223
224 LOG(4, ("INIT: powerup\n"));
225 LOG(4, ("INIT: Detected %s (%s)\n", si->adi.name, si->adi.chipset));
226 if (si->settings.logmask & 0x80000000) nm_dump_configuration_space();
227
228 /* set ISA registermapping to VGA colormode */
229 temp = (ISARB(MISCR) | 0x01);
230 /* we need to wait a bit or the card will mess-up it's register values.. */
231 snooze(10);
232 ISAWB(MISCW, temp);
233
234 /* unlock cards GRAPHICS registers (any other value than 0x26 should lock it again) */
235 ISAGRPHW(GRPHXLOCK, 0x26);
236
237 /* unlock cards CRTC registers */
238 //don't touch: most cards get into trouble on this!
239 // ISAGRPHW(GENLOCK, 0x00);
240
241 /* initialize the shared_info struct */
242 set_specs();
243 /* log the struct settings */
244 dump_specs();
245
246 /* activate PCI access: b7 = framebuffer, b6 = registers */
247 ISAGRPHW(IFACECTRL2, 0xc0);
248
249 /* disable VGA-mode cursor (just to be sure) */
250 ISACRTCW(VGACURCTRL, 0x00);
251
252 /* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */
253 /*if (si->settings.usebios || (result != B_OK)) */return nm_general_bios_to_powergraphics();
254
255 /*power up the PLLs,LUT,DAC*/
256 LOG(2,("INIT: powerup\n"));
257
258 /* turn off both displays and the hardcursor (also disables transfers) */
259 nm_crtc_dpms(false, false, false);
260 nm_crtc_cursor_hide();
261
262 /* setup sequencer clocking mode */
263 ISASEQW(CLKMODE, 0x21);
264
265 //fixme: setup coldstart capability...
266
267 /* turn on display */
268 nm_crtc_dpms(true, true, true);
269
270 return B_OK;
271 }
272
nm_general_output_select()273 status_t nm_general_output_select()
274 {
275 /* log currently selected output */
276 switch (nm_general_output_read() & 0x03)
277 {
278 case 0x01:
279 LOG(2, ("INIT: external CRT only mode active\n"));
280 break;
281 case 0x02:
282 LOG(2, ("INIT: internal LCD only mode active\n"));
283 break;
284 case 0x03:
285 LOG(2, ("INIT: simultaneous LCD/CRT mode active\n"));
286 break;
287 }
288 return B_OK;
289 }
290
nm_general_output_read()291 uint8 nm_general_output_read()
292 {
293 uint8 size_outputs;
294
295 /* read panelsize and currently active outputs */
296 size_outputs = ISAGRPHR(PANELCTRL1);
297
298 /* update noted currently active outputs if prudent:
299 * - tracks active output devices, even if the keyboard shortcut is used because
300 * using that key will take the selected output devices out of DPMS sleep mode
301 * if programmed via these bits;
302 * - when the shortcut key is not used, and DPMS was in a power-saving mode while
303 * programmed via these bits, an output device will (still) be shut-off. */
304 if (si->ps.card_type < NM2200)
305 {
306 /* both output devices do DPMS via these bits.
307 * if one of the bits is on we have a valid setting if no power-saving mode
308 * is active, or the keyboard shortcut key for selecting output devices has
309 * been used during power-saving mode. */
310 if (size_outputs & 0x03) si->ps.outputs = (size_outputs & 0x03);
311 }
312 else
313 {
314 /* check if any power-saving mode active */
315 if (!(ISASEQR(CLKMODE) & 0x20))
316 {
317 /* screen is on:
318 * we can 'safely' copy both output devices settings... */
319 if (size_outputs & 0x03)
320 {
321 si->ps.outputs = (size_outputs & 0x03);
322 }
323 else
324 {
325 /* ... unless no output is active, as this is illegal then */
326 si->ps.outputs = 0x02;
327
328 LOG(4, ("INIT: illegal outputmode detected, assuming internal mode!\n"));
329 }
330 }
331 else
332 {
333 /* screen is off:
334 * only the internal panel does DPMS via these bits, so the external setting
335 * can always be copied */
336 si->ps.outputs &= 0xfe;
337 si->ps.outputs |= (size_outputs & 0x01);
338 /* if the panel is on, we can note that (the shortcut key has been used) */
339 if (size_outputs & 0x02) si->ps.outputs |= 0x02;
340 }
341 }
342
343 return ((size_outputs & 0xfc) | (si->ps.outputs & 0x03));
344 }
345
346 /* basic change of card state from VGA to powergraphics -> should work from BIOS init state*/
347 static
nm_general_bios_to_powergraphics()348 status_t nm_general_bios_to_powergraphics()
349 {
350 uint8 temp;
351
352 LOG(2, ("INIT: Skipping card coldstart!\n"));
353
354 /* turn off display */
355 nm_crtc_dpms(false, false, false);
356
357 /* set card to 'enhanced' mode: (only VGA standard registers used for NeoMagic cards) */
358 /* (keep) card enabled, set plain normal memory usage, no old VGA 'tricks' ... */
359 ISACRTCW(MODECTL, 0xc3);
360 /* ... plain sequential memory use, more than 64Kb RAM installed,
361 * switch to graphics mode ... */
362 ISASEQW(MEMMODE, 0x0e);
363 /* ... disable bitplane tweaking ... */
364 /* note:
365 * NeoMagic cards have custom b4-b7 use in this register! */
366 ISAGRPHW(ENSETRESET, 0x80);
367 /* ... no logical function tweaking with display data, no data rotation ... */
368 ISAGRPHW(DATAROTATE, 0x00);
369 /* ... reset read map select to plane 0 ... */
370 ISAGRPHW(READMAPSEL, 0x00);
371 /* ... set standard mode ... */
372 ISAGRPHW(MODE, 0x00);
373 /* ... ISA framebuffer mapping is 64Kb window, switch to graphics mode (again),
374 * select standard adressing ... */
375 ISAGRPHW(MISC, 0x05);
376 /* ... disable bit masking ... */
377 ISAGRPHW(BITMASK, 0xff);
378 /* ... attributes are in color, switch to graphics mode (again) ... */
379 ISAATBW(MODECTL, 0x01);
380 /* ... set overscan color to black ... */
381 ISAATBW(OSCANCOLOR, 0x00);
382 /* ... enable all color planes ... */
383 ISAATBW(COLPLANE_EN, 0x0f);
384 /* ... reset horizontal pixelpanning ... */
385 ISAATBW(HORPIXPAN, 0x00);
386 /* ... reset colorpalette groupselect bits ... */
387 ISAATBW(COLSEL, 0x00);
388 /* ... do unknown standard VGA register ... */
389 /* note:
390 * NeoMagic cards have custom b6 use in this register! */
391 ISAATBW(0x16, 0x01);
392 /* ... and enable all four byteplanes. */
393 ISASEQW(MAPMASK, 0x0f);
394
395 /* setup sequencer clocking mode */
396 ISASEQW(CLKMODE, 0x21);
397
398 /* enable memory above 256Kb: set b4 (disables adress wraparound at 256Kb boundary) */
399 ISAGRPHW(FBSTADDE, 0x10);
400
401 /* this register has influence on the CRTC framebuffer offset, so reset! */
402 //fixme: investigate further...
403 ISAGRPHW(0x15, 0x00);
404
405 /* enable fast PCI write bursts (b4-5) */
406 temp = ((ISAGRPHR(IFACECTRL1) & 0x0f) | 0x30);
407 /* we need to wait a bit or the card will mess-up it's register values.. */
408 snooze(10);
409 ISAGRPHW(IFACECTRL1, temp);
410
411 /* this speeds up RAM writes according to XFree driver */
412 // fixme: don't touch until more is known: part of RAM or CORE PLL???
413 // ISAGRPHW(SPEED, 0xc0);
414
415 /* turn on display */
416 nm_crtc_dpms(true, true, true);
417
418 return B_OK;
419 }
420
421 /* Check if mode virtual_size adheres to the cards _maximum_ contraints, and modify
422 * virtual_size to the nearest valid maximum for the mode on the card if not so.
423 * Then: check if virtual_width adheres to the cards _multiple_ constraints, and
424 * create mode slopspace if not so.
425 * We use acc multiple constraints here if we expect we can use acceleration, because
426 * acc constraints are worse than CRTC constraints.
427 *
428 * Mode slopspace is reflected in fbc->bytes_per_row BTW. */
nm_general_validate_pic_size(display_mode * target,uint32 * bytes_per_row,bool * acc_mode)429 status_t nm_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode)
430 {
431 /* Note:
432 * This routine assumes that the CRTC memory pitch granularity is 'smaller than',
433 * or 'equals' the acceleration engine memory pitch granularity! */
434
435 uint32 video_pitch = 0;
436 uint32 crtc_mask;
437 uint8 depth = 8;
438
439 /* determine pixel multiple based on CRTC memory pitch constraints.
440 * (Note: Don't mix this up with CRTC timing contraints! Those are
441 * multiples of 8 for horizontal, 1 for vertical timing.)
442 *
443 * CRTC pitch constraints are 'officially' the same for all Neomagic cards */
444 switch (si->ps.card_type)
445 {
446 case NM2070:
447 switch (target->space)
448 {
449 case B_CMAP8: crtc_mask = 0x07; depth = 8; break;
450 /* Note for NM2070 only:
451 * The following depths have bandwidth trouble (pixel noise) with the
452 * 'official' crtc_masks (used as defaults below). Masks of 0x1f are
453 * needed (confirmed 15 and 16 bit spaces) to minimize this. */
454 //fixme: doublecheck for NM2090 and NM2093: correct code if needed!
455 case B_RGB15: crtc_mask = 0x1f; depth = 16; break;
456 case B_RGB16: crtc_mask = 0x1f; depth = 16; break;
457 case B_RGB24: crtc_mask = 0x1f; depth = 24; break;
458 default:
459 LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
460 return B_ERROR;
461 }
462 break;
463 default:
464 switch (target->space)
465 {
466 case B_CMAP8: crtc_mask = 0x07; depth = 8; break;
467 case B_RGB15: crtc_mask = 0x03; depth = 16; break;
468 case B_RGB16: crtc_mask = 0x03; depth = 16; break;
469 case B_RGB24: crtc_mask = 0x07; depth = 24; break;
470 default:
471 LOG(8,("INIT: unsupported colorspace: 0x%08x\n", target->space));
472 return B_ERROR;
473 }
474 break;
475 }
476
477 /* check if we can setup this mode with acceleration: */
478 *acc_mode = true;
479
480 /* pre-NM2200 cards don't support accelerated 24bit modes */
481 if ((si->ps.card_type < NM2200) && (target->space == B_RGB24)) *acc_mode = false;
482
483 /* virtual_width */
484 if (si->ps.card_type == NM2070)
485 {
486 /* confirmed NM2070 */
487 if (target->virtual_width > 1024) *acc_mode = false;
488 }
489 else
490 {
491 /* confirmed for all cards */
492 if (target->virtual_width > 1600) *acc_mode = false;
493 }
494
495 /* virtual_height (confirmed NM2070, NM2097, NM2160 and NM2200 */
496 if (target->virtual_height > 1024) *acc_mode = false;
497
498 /* now check virtual_size based on CRTC constraints and modify if needed */
499 //fixme: checkout cardspecs here!! (NM2160 can do 8192 _bytes_ at least (in theory))
500 {
501 /* virtual_width */
502 switch(target->space)
503 {
504 case B_CMAP8:
505 if (target->virtual_width > 16368)
506 target->virtual_width = 16368;
507 break;
508 case B_RGB15_LITTLE:
509 case B_RGB16_LITTLE:
510 if (target->virtual_width > 8184)
511 target->virtual_width = 8184;
512 break;
513 case B_RGB24_LITTLE:
514 if (target->virtual_width > 5456)
515 target->virtual_width = 5456;
516 break;
517 }
518
519 /* virtual_height: The only constraint here is the cards memory size which is
520 * checked later on in ProposeMode: virtual_height is adjusted then if needed.
521 * 'Limiting here' to the variable size that's at least available (uint16). */
522 if (target->virtual_height > 65535) target->virtual_height = 65535;
523 }
524
525 /* OK, now we know that virtual_width is valid, and it's needing no slopspace if
526 * it was confined above, so we can finally calculate safely if we need slopspace
527 * for this mode... */
528 if (*acc_mode)
529 {
530 if (si->ps.card_type == NM2070)
531 {
532 uint32 acc_mask = 0;
533
534 /* determine pixel multiple based on 2D engine constraints */
535 switch (target->space)
536 {
537 case B_CMAP8: acc_mask = 0x07; break;
538 /* Note:
539 * The following depths have actual acc_masks of 0x03. 0x1f is used
540 * because on lower acc_masks more bandwidth trouble arises.
541 * (pixel noise) */
542 //fixme: doublecheck for NM2090 and NM2093: correct code if needed!
543 case B_RGB15: acc_mask = 0x1f; break;
544 case B_RGB16: acc_mask = 0x1f; break;
545 }
546 video_pitch = ((target->virtual_width + acc_mask) & ~acc_mask);
547 }
548 else
549 {
550 /* Note:
551 * We prefer unaccelerated modes above accelerated ones here if not enough
552 * RAM exists and the mode can be closer matched to the requested one if
553 * unaccelerated. We do this because of the large amount of slopspace
554 * sometimes needed here to keep a mode accelerated. */
555
556 uint32 mem_avail, bytes_X_height;
557
558 /* calculate amount of available memory */
559 mem_avail = (si->ps.memory_size * 1024);
560 if (si->settings.hardcursor) mem_avail -= si->ps.curmem_size;
561 /* helper */
562 bytes_X_height = (depth >> 3) * target->virtual_height;
563
564 /* Accelerated modes work with a table, there are very few fixed settings.. */
565 if (target->virtual_width == 640) video_pitch = 640;
566 else
567 if (target->virtual_width <= 800)
568 {
569 if (((800 * bytes_X_height) > mem_avail) &&
570 (target->virtual_width < (800 - crtc_mask)))
571 *acc_mode = false;
572 else
573 video_pitch = 800;
574 }
575 else
576 if (target->virtual_width <= 1024)
577 {
578 if (((1024 * bytes_X_height) > mem_avail) &&
579 (target->virtual_width < (1024 - crtc_mask)))
580 *acc_mode = false;
581 else
582 video_pitch = 1024;
583 }
584 else
585 if (target->virtual_width <= 1152)
586 {
587 if (((1152 * bytes_X_height) > mem_avail) &&
588 (target->virtual_width < (1152 - crtc_mask)))
589 *acc_mode = false;
590 else
591 video_pitch = 1152;
592 }
593 else
594 if (target->virtual_width <= 1280)
595 {
596 if (((1280 * bytes_X_height) > mem_avail) &&
597 (target->virtual_width < (1280 - crtc_mask)))
598 *acc_mode = false;
599 else
600 video_pitch = 1280;
601 }
602 else
603 if (target->virtual_width <= 1600)
604 {
605 if (((1600 * bytes_X_height) > mem_avail) &&
606 (target->virtual_width < (1600 - crtc_mask)))
607 *acc_mode = false;
608 else
609 video_pitch = 1600;
610 }
611 }
612 }
613 if (!*acc_mode)
614 video_pitch = ((target->virtual_width + crtc_mask) & ~crtc_mask);
615
616 LOG(2,("INIT: memory pitch will be set to %d pixels for colorspace 0x%08x\n",
617 video_pitch, target->space));
618 if (target->virtual_width != video_pitch)
619 LOG(2,("INIT: effective mode slopspace is %d pixels\n",
620 (video_pitch - target->virtual_width)));
621
622 /* now calculate bytes_per_row for this mode */
623 *bytes_per_row = video_pitch * (depth >> 3);
624
625 return B_OK;
626 }
627