From 80d8f99ee84d2dedd9915146fe5c5acdb8efebfb Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Mon, 2 Aug 2004 20:37:59 +0000 Subject: [PATCH] Build system conversion and check in of ATI Mach64 driver for MYOB. Based on source written by Rene MacKinney. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8531 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/accelerants/Jamfile | 2 + .../accelerants/atimach64/Acceleration.c | 434 ++++ src/add-ons/accelerants/atimach64/Cursor.c | 210 ++ .../accelerants/atimach64/EngineManagment.c | 83 + .../accelerants/atimach64/GetAccelerantHook.c | 86 + .../accelerants/atimach64/GetModeInfo.c | 73 + .../accelerants/atimach64/GlobalData.c | 10 + .../accelerants/atimach64/GlobalData.h | 16 + .../accelerants/atimach64/InitAccelerant.c | 372 ++++ src/add-ons/accelerants/atimach64/Jamfile | 21 + src/add-ons/accelerants/atimach64/Mach64.c | 447 +++++ src/add-ons/accelerants/atimach64/Mach64.h | 5 + .../accelerants/atimach64/Mach64fifo.c | 1738 +++++++++++++++++ .../accelerants/atimach64/Mach64fifo.h | 72 + .../atimach64/ProposeDisplayMode.c | 399 ++++ .../accelerants/atimach64/SetDisplayMode.c | 285 +++ src/add-ons/accelerants/atimach64/generic.h | 46 + src/add-ons/kernel/drivers/graphics/Jamfile | 2 + .../kernel/drivers/graphics/atimach64/COPYING | 339 ++++ .../kernel/drivers/graphics/atimach64/Jamfile | 19 + .../drivers/graphics/atimach64/driver.c | 976 +++++++++ .../drivers/graphics/atimach64/m64info.c | 256 +++ 22 files changed, 5891 insertions(+) create mode 100644 src/add-ons/accelerants/atimach64/Acceleration.c create mode 100644 src/add-ons/accelerants/atimach64/Cursor.c create mode 100644 src/add-ons/accelerants/atimach64/EngineManagment.c create mode 100644 src/add-ons/accelerants/atimach64/GetAccelerantHook.c create mode 100644 src/add-ons/accelerants/atimach64/GetModeInfo.c create mode 100644 src/add-ons/accelerants/atimach64/GlobalData.c create mode 100644 src/add-ons/accelerants/atimach64/GlobalData.h create mode 100644 src/add-ons/accelerants/atimach64/InitAccelerant.c create mode 100644 src/add-ons/accelerants/atimach64/Jamfile create mode 100644 src/add-ons/accelerants/atimach64/Mach64.c create mode 100644 src/add-ons/accelerants/atimach64/Mach64.h create mode 100644 src/add-ons/accelerants/atimach64/Mach64fifo.c create mode 100644 src/add-ons/accelerants/atimach64/Mach64fifo.h create mode 100644 src/add-ons/accelerants/atimach64/ProposeDisplayMode.c create mode 100644 src/add-ons/accelerants/atimach64/SetDisplayMode.c create mode 100644 src/add-ons/accelerants/atimach64/generic.h create mode 100644 src/add-ons/kernel/drivers/graphics/atimach64/COPYING create mode 100644 src/add-ons/kernel/drivers/graphics/atimach64/Jamfile create mode 100644 src/add-ons/kernel/drivers/graphics/atimach64/driver.c create mode 100644 src/add-ons/kernel/drivers/graphics/atimach64/m64info.c diff --git a/src/add-ons/accelerants/Jamfile b/src/add-ons/accelerants/Jamfile index eee69023cf..44b44d867f 100644 --- a/src/add-ons/accelerants/Jamfile +++ b/src/add-ons/accelerants/Jamfile @@ -6,3 +6,5 @@ SubInclude OBOS_TOP src add-ons accelerants neomagic ; SubInclude OBOS_TOP src add-ons accelerants nvidia ; SubInclude OBOS_TOP src add-ons accelerants radeon ; SubInclude OBOS_TOP src add-ons accelerants tdfx ; + +SubIncludeGPL OBOS_TOP src add-ons accelerants atimach64 ; diff --git a/src/add-ons/accelerants/atimach64/Acceleration.c b/src/add-ons/accelerants/atimach64/Acceleration.c new file mode 100644 index 0000000000..0ecb54368b --- /dev/null +++ b/src/add-ons/accelerants/atimach64/Acceleration.c @@ -0,0 +1,434 @@ +#include + +#include "GlobalData.h" +#include "generic.h" + +#define STICKY_REGS 1 + +#define WRITE_REG(x, y) outw(x, y) + +#define wait_for_slots(num) WaitQueue(num) + +/*#define wait_for_slots(numSlots) \ + { \ + uint32 FifoReg; \ + \ + do \ + { \ + READ_REG(FIFO_STAT, FifoReg); \ + } \ + while ((FifoReg & 0xFFFF) >> (16 - numSlots)); \ + } +*/ +void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count) { + + uint32 Offset, Pitch; + uint32 BppEncoding; + uint32 XDir; + uint32 YDir; + + uint32 src_top, src_left; + uint32 dest_top, dest_left; + uint32 width, height; + + uint32 scissor_x = (si->dm.virtual_width - 1) << 16; + uint32 scissor_y = (si->dm.virtual_height - 1) << 16; + + // Perform required calculations and do the blit. + // start of frame buffer + Offset = 1024; + Offset = Offset >> 3; // qword offset of the frame buffer in card memory; had + // better be qword-aligned. + + Pitch = si->dm.virtual_width; + Pitch = (Pitch + 7) >> 3; // frame buffer stride in pixels*8 + + // encode pixel format + switch (si->dm.space & ~0x3000) + { + case B_CMAP8: + BppEncoding = 0x2; + break; + case B_RGB15_BIG: + case B_RGBA15_BIG: + case B_RGB15_LITTLE: + case B_RGBA15_LITTLE: + BppEncoding = 0x3; + break; + case B_RGB16_BIG: + case B_RGB16_LITTLE: + BppEncoding = 0x4; + break; + case B_RGB32_BIG: + case B_RGBA32_BIG: + case B_RGB32_LITTLE: + case B_RGBA32_LITTLE: + default: + BppEncoding = 0x6; + } + + BppEncoding = (BppEncoding << 28) | (BppEncoding << 16) | (BppEncoding << 8) + | (BppEncoding << 4) | BppEncoding; + +#if STICKY_REGS > 0 + wait_for_slots(10); + + WRITE_REG(SC_LEFT_RIGHT, scissor_x); + WRITE_REG(SC_TOP_BOTTOM, scissor_y); + WRITE_REG(DP_WRITE_MASK, 0xFFFFFFFF); + WRITE_REG(DP_PIX_WIDTH, BppEncoding); + WRITE_REG(DP_MIX, 0x00070007); // ROP = SRC + WRITE_REG(DP_SRC, 0x00000300); + WRITE_REG(CLR_CMP_CNTL, 0x0); + + // Pitch and offset had better not be out of range. + WRITE_REG(SRC_OFF_PITCH, (Pitch << 22) | Offset); + WRITE_REG(DST_OFF_PITCH, (Pitch << 22) | Offset); + WRITE_REG(SRC_CNTL, 0x0); + /* update fifo count */ + si->engine.count += 10; +#endif + + /* program the blit */ + while (count--) { + src_left = list->src_left; + src_top = list->src_top; + dest_left = list->dest_left; + dest_top = list->dest_top; + width = list->width + 1; /* + 1 because it seems to be non-inclusive */ + height = list->height + 1; + + // Adjust direction of blitting to allow for overlapping source and destination. + if (src_left < dest_left) + { + XDir = 0; // right to left + src_left += (width - 1); + dest_left += (width - 1); + } + else + XDir = 1; // left to right + + if (src_top < dest_top) + { + YDir = 0; // bottom to top + src_top += (height - 1); + dest_top += (height - 1); + } + else + YDir = 1; // top to bottom + + + // Set up the rectangle blit + + // Critital section - accessing card registers. + //lock_card(); + + +#if STICKY_REGS > 0 + wait_for_slots(5); +#else + wait_for_slots(15); + + WRITE_REG(SC_LEFT_RIGHT, scissor_x); + WRITE_REG(SC_TOP_BOTTOM, scissor_y); + WRITE_REG(DP_WRITE_MASK, 0xFFFFFFFF); + WRITE_REG(DP_PIX_WIDTH, BppEncoding); + WRITE_REG(DP_MIX, 0x00070007); // ROP = SRC + WRITE_REG(DP_SRC, 0x00000300); + WRITE_REG(CLR_CMP_CNTL, 0x0); + + // Pitch and offset had better not be out of range. + WRITE_REG(SRC_OFF_PITCH, (Pitch << 22) | Offset); + WRITE_REG(DST_OFF_PITCH, (Pitch << 22) | Offset); + WRITE_REG(SRC_CNTL, 0x0); +#endif + + WRITE_REG(SRC_WIDTH1, width); + WRITE_REG(SRC_Y_X, ((uint32)src_left << 16) | src_top); + + // Pitch and offset had better not be out of range. + WRITE_REG(DST_CNTL, (YDir << 1) | XDir); + WRITE_REG(DST_Y_X, ((uint32)dest_left << 16) | dest_top); + WRITE_REG(DST_HEIGHT_WIDTH, ((uint32)width << 16) | height); // This triggers drawing. + +#if STICKY_REGS + /* update fifo count */ + si->engine.count += 5; +#else + /* update fifo count */ + si->engine.count += 15; +#endif + /* next one */ + list++; + } +} + +void hardware_rectangle(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count, uint32 ROP) { + + uint32 Offset; + uint32 Pitch; + uint32 Y; + uint32 X; + uint32 Width; + uint32 Height; + uint32 Colour; + uint32 BppEncoding; + +#if STICKY_REGS > 0 + uint32 scissor_x = (si->dm.virtual_width - 1) << 16; + uint32 scissor_y = (si->dm.virtual_height - 1) << 16; +#endif + + // Perform required calculations and do the blit. + // start of frame buffer + Offset = 1024; + Offset = Offset >> 3; // qword offset of the frame buffer in card memory; had + // better be qword-aligned. + + Pitch = si->dm.virtual_width; + Pitch = (Pitch + 7) >> 3; // frame buffer stride in pixels*8 + + // Don't need this - rectangle is in frame buffer co-ordinates. +// X += (uint32) (CardInfo.Display.DisplayXPos); +// Y += (uint32) (CardInfo.Display.DisplayYPos); + + // Fill colour dword with specified colour, though only ls should be necessary. + switch (si->dm.space & ~0x3000) + { + case B_CMAP8: + BppEncoding = 0x2; + colorIndex &= 0xFF; + Colour = colorIndex | (colorIndex << 8) | (colorIndex << 16) | (colorIndex << 24); + break; + case B_RGB15_BIG: + case B_RGBA15_BIG: + case B_RGB15_LITTLE: + case B_RGBA15_LITTLE: + BppEncoding = 0x3; + colorIndex &= 0xFFFF; + Colour = colorIndex | (colorIndex << 16); + break; + case B_RGB16_BIG: + case B_RGB16_LITTLE: + BppEncoding = 0x4; + colorIndex &= 0xFFFF; + Colour = colorIndex | (colorIndex << 16); + break; + case B_RGB32_BIG: + case B_RGBA32_BIG: + case B_RGB32_LITTLE: + case B_RGBA32_LITTLE: + default: + BppEncoding = 0x6; + Colour = colorIndex; + } + + BppEncoding = (BppEncoding << 28) | (BppEncoding << 16) | (BppEncoding << 8) | (BppEncoding << 4) | BppEncoding; + +#if STICKY_REGS > 0 + wait_for_slots(11); + // This seems to be needed even though we aren't using a source trajectory. + WRITE_REG(SRC_CNTL, 0x0); + + // Pitch and offset had better not be out of range. + WRITE_REG(DST_OFF_PITCH, (Pitch << 22) | Offset); + + WRITE_REG(DP_FRGD_CLR, Colour); + WRITE_REG(DP_WRITE_MASK, 0xFFFFFFFF); + WRITE_REG(DP_PIX_WIDTH, BppEncoding); + WRITE_REG(DP_MIX, ROP); + WRITE_REG(DP_SRC, 0x00000100); + + WRITE_REG(CLR_CMP_CNTL, 0x0); + WRITE_REG(GUI_TRAJ_CNTL, 0x3); + WRITE_REG(SC_LEFT_RIGHT, scissor_x); + WRITE_REG(SC_TOP_BOTTOM, scissor_y); + /* update fifo count */ + si->engine.count += 11; +#endif + + while (count--) { + + X = list->left; + Y = list->top; + Width = list->right; + Width = Width - X + 1; + Height = list->bottom; + Height = Height - Y + 1; + +#if STICKY_REGS > 0 + wait_for_slots(2); +#else + wait_for_slots(13); + // This seems to be needed even though we aren't using a source trajectory. + WRITE_REG(SRC_CNTL, 0x0); + + // Pitch and offset had better not be out of range. + WRITE_REG(DST_OFF_PITCH, (Pitch << 22) | Offset); + + WRITE_REG(DP_FRGD_CLR, Colour); + WRITE_REG(DP_WRITE_MASK, 0xFFFFFFFF); + WRITE_REG(DP_PIX_WIDTH, BppEncoding); + WRITE_REG(DP_MIX, ROP); + WRITE_REG(DP_SRC, 0x00000100); + + WRITE_REG(CLR_CMP_CNTL, 0x0); + WRITE_REG(GUI_TRAJ_CNTL, 0x3); + + WRITE_REG(SC_LEFT_RIGHT, ((X + Width - 1) << 16) | X); + WRITE_REG(SC_TOP_BOTTOM, ((Y + Height - 1) << 16) | Y); +#endif + + // X and Y should have been clipped to frame buffer, and so should be in range. + WRITE_REG(DST_Y_X, (X << 16) | Y); + WRITE_REG(DST_HEIGHT_WIDTH, (Width << 16) | Height); // This triggers drawing. + +#if STICKY_REGS + /* update fifo count */ + si->engine.count += 2; +#else + /* update fifo count */ + si->engine.count += 13; +#endif + + /* next rect */ + list++; + } + +} + +void FILL_RECTANGLE(engine_token *et, uint32 colorIndex, fill_rect_params *list, uint32 count) { + hardware_rectangle(et, colorIndex, list, count, 0x00070007); // ROP = SRC +} + +void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count) { + hardware_rectangle(et, 0xFFFFFFFF, list, count, 0x00000000); // ROP = !DST +} + +void FILL_SPAN(engine_token *et, uint32 colorIndex, uint16 *list, uint32 count) { + uint32 Offset; + uint32 Pitch; + uint32 Y; + uint32 X; + uint32 Width; + uint32 Height; + uint32 Colour; + uint32 BppEncoding; + + +#if STICKY_REGS > 0 + uint32 scissor_x = (si->dm.virtual_width - 1) << 16; + uint32 scissor_y = (si->dm.virtual_height - 1) << 16; +#endif + + // Perform required calculations and do the blit. + // start of frame buffer + Offset = 1024; + Offset = Offset >> 3; // qword offset of the frame buffer in card memory; had + // better be qword-aligned. + + Pitch = si->dm.virtual_width; + Pitch = (Pitch + 7) >> 3; // frame buffer stride in pixels*8 + + // Fill colour dword with specified colour, though only ls should be necessary. + switch (si->dm.space & ~0x3000) + { + case B_CMAP8: + BppEncoding = 0x2; + colorIndex &= 0xFF; + Colour = colorIndex | (colorIndex << 8) | (colorIndex << 16) | (colorIndex << 24); + break; + case B_RGB15_BIG: + case B_RGBA15_BIG: + case B_RGB15_LITTLE: + case B_RGBA15_LITTLE: + BppEncoding = 0x3; + colorIndex &= 0xFFFF; + Colour = colorIndex | (colorIndex << 16); + break; + case B_RGB16_BIG: + case B_RGB16_LITTLE: + BppEncoding = 0x4; + colorIndex &= 0xFFFF; + Colour = colorIndex | (colorIndex << 16); + break; + case B_RGB32_BIG: + case B_RGBA32_BIG: + case B_RGB32_LITTLE: + case B_RGBA32_LITTLE: + default: + BppEncoding = 0x6; + Colour = colorIndex; + } + + BppEncoding = (BppEncoding << 28) | (BppEncoding << 16) | (BppEncoding << 8) | (BppEncoding << 4) | BppEncoding; + + +#if STICKY_REGS > 0 + wait_for_slots(11); + // This seems to be needed even though we aren't using a source trajectory. + WRITE_REG(SRC_CNTL, 0x0); + + // Pitch and offset had better not be out of range. + WRITE_REG(DST_OFF_PITCH, (Pitch << 22) | Offset); + + WRITE_REG(DP_FRGD_CLR, Colour); + WRITE_REG(DP_WRITE_MASK, 0xFFFFFFFF); + WRITE_REG(DP_PIX_WIDTH, BppEncoding); + WRITE_REG(DP_MIX, 0x00070007); // ROP = SRC + WRITE_REG(DP_SRC, 0x00000100); + + WRITE_REG(CLR_CMP_CNTL, 0x0); + WRITE_REG(GUI_TRAJ_CNTL, 0x3); + WRITE_REG(SC_LEFT_RIGHT, scissor_x); + WRITE_REG(SC_TOP_BOTTOM, scissor_y); + /* update fifo count */ + si->engine.count += 11; +#endif + /* span lines are always one pixel tall */ + Height = 1; + while (count--) { + + Y = (uint32)*list++; + X = (uint32)*list++; + Width = (uint32)*list++; + Width = Width - X + 1; + +#if STICKY_REGS > 0 + wait_for_slots(2); +#else + wait_for_slots(13); + // This seems to be needed even though we aren't using a source trajectory. + WRITE_REG(SRC_CNTL, 0x0); + + // Pitch and offset had better not be out of range. + WRITE_REG(DST_OFF_PITCH, (Pitch << 22) | Offset); + + WRITE_REG(DP_FRGD_CLR, Colour); + WRITE_REG(DP_WRITE_MASK, 0xFFFFFFFF); + WRITE_REG(DP_PIX_WIDTH, BppEncoding); + WRITE_REG(DP_MIX, 0x00070007); // ROP = SRC + WRITE_REG(DP_SRC, 0x00000100); + + WRITE_REG(CLR_CMP_CNTL, 0x0); + WRITE_REG(GUI_TRAJ_CNTL, 0x3); + + WRITE_REG(SC_LEFT_RIGHT, ((X + Width - 1) << 16) | X); + WRITE_REG(SC_TOP_BOTTOM, ((Y + Height - 1) << 16) | Y); +#endif + + // X and Y should have been clipped to frame buffer, and so should be in range. + WRITE_REG(DST_Y_X, (X << 16) | Y); + WRITE_REG(DST_HEIGHT_WIDTH, (Width << 16) | Height); // This triggers drawing. + +#if STICKY_REGS + /* update fifo count */ + si->engine.count += 2; +#else + /* update fifo count */ + si->engine.count += 13; +#endif + + } + +} diff --git a/src/add-ons/accelerants/atimach64/Cursor.c b/src/add-ons/accelerants/atimach64/Cursor.c new file mode 100644 index 0000000000..506b40ec7a --- /dev/null +++ b/src/add-ons/accelerants/atimach64/Cursor.c @@ -0,0 +1,210 @@ +#include "GlobalData.h" +#include "generic.h" + +void set_cursor_colors(void); +uint8 bit_mirror(uint8 bits); +uint16 bit_merger(uint8 andbits, uint8 xorbits); + +void set_cursor_colors(void) { + /* a place-holder for a routine to set the cursor colors */ + /* In our sample driver, it's only called by the INIT_ACCELERANT() */ + + /* Cursor color 0 is black */ + + outw(CUR_CLR0, 0x00000000); + + /* Cursor color 1 is white */ + + outw(CUR_CLR1, 0xffffffff); + +} + +uint8 +bit_mirror(uint8 bits) +{ + int i; + uint8 res = 0; + + for(i=0; i<8; i++) { + res |= (1 & (bits>>i)) <<(7-i); + + } + + return res; +} + +uint16 +bit_merger(uint8 andbits, uint8 xorbits) +{ + int i; + uint16 res = 0; + uint8 bits = 0; + + for(i=0; i<8; i++) { + bits = (((xorbits & (1<>i)<<1) | ((andbits & (1<>i); + switch (bits){ + case 0: /* Transparent is 10 */ + res |= (2 << (i*2)); + break; + case 2: /* Inversion is 11 */ + res |= (3 << (i*2)); + break; + case 1: /* White is color 1 */ + res |= (1 << (i*2)); + break; + case 3: /* Black is color 0 */ + break; + } + } + + return res; + +} + +status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask) { + + int i, j, k; + uint8 andM, xorM; + uint16 *cdata = (uint16 *)si->cursor.data; + + /* NOTE: Currently, for BeOS, cursor width and height must be equal to 16. */ + + if ((width != 16) || (height != 16)) + { + return B_ERROR; + } + else if ((hot_x >= width) || (hot_y >= height)) + { + return B_ERROR; + } + else + { + + /* Turn off cursor */ + SHOW_CURSOR(false); + + + /* Fill up data */ + k = 0; + for(i = 0; i < height; i++) { + for(j = 0; j < (width / 8); j++) { + andM = bit_mirror(~*(andMask++)); + xorM = bit_mirror(*(xorMask++)); + + /* convert 8 bits to 16 bits of mask */ + cdata[j + (i*8)] = + bit_merger(andM, xorM); + + } + + } + /* Update cursor variables appropriately. */ + si->cursor.width = width; + si->cursor.height = height; + si->cursor.hot_x = hot_x; + si->cursor.hot_y = hot_y; + + /* Turn on cursor */ + SHOW_CURSOR(true); + } + + return B_OK; +} + +/* +Move the cursor to the specified position on the desktop. If we're +using some kind of virtual desktop, adjust the display start position +accordingly and position the cursor in the proper "virtual" location. +*/ +void +MOVE_CURSOR(uint16 x, uint16 y) { + + bool move_screen = false; + uint16 hds = si->dm.h_display_start; /* the current horizontal starting pixel */ + uint16 vds = si->dm.v_display_start; /* the current vertical starting line */ + int xoff, yoff; /* offsets of cursor if it goes out of the screen */ + /* + Most cards can't set the starting horizontal pixel to anything but a multiple + of eight. If your card can, then you can change the adjustment factor here. + Oftentimes the restriction is mode dependant, so you could be fancier and + perhaps get smoother horizontal scrolling with more work. It's a sample driver, + so we're going to be lazy here. + */ + uint16 h_adjust = 7; /* a mask to make horizontal values a multiple of 8 */ + + /* clamp cursor to virtual display */ + if (x >= si->dm.virtual_width) x = si->dm.virtual_width - 1; + if (y >= si->dm.virtual_height) y = si->dm.virtual_height - 1; + + /* adjust h/v_display_start to move cursor onto screen */ + if (x >= (si->dm.timing.h_display + hds)) { + hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust; + move_screen = true; + } else if (x < hds) { + hds = x & ~h_adjust; + move_screen = true; + } + if (y >= (si->dm.timing.v_display + vds)) { + vds = y - si->dm.timing.v_display + 1; + move_screen = true; + } else if (y < vds) { + vds = y; + move_screen = true; + } + /* reposition the desktop on the display if required */ + if (move_screen) MOVE_DISPLAY(hds,vds); + + /* put cursor in correct physical position */ + x -= hds; + y -= vds; + + /* Take care of hot_x hot_y */ + xoff = x - si->cursor.hot_x; + yoff = y - si->cursor.hot_y; + + /* Do we have to fake the cursor going out of the screen ? */ + if (xoff < 0) { + xoff = -xoff; + } else { + xoff = 0; + x -= si->cursor.hot_x; + } + + if (yoff < 0) { + yoff = -yoff; + } else { + yoff = 0; + y -= si->cursor.hot_y; + } + + /* Position the offset of the cursor */ + outw(CUR_HORZ_VERT_OFF, (yoff << 16) | xoff); + + + /* position the cursor on the display */ + /* this will be card dependant */ + + /* printf(" Place %08x %d %d \n", si->regs + CUR_HORZ_VERT_POSN, x, y);*/ + + outw(CUR_HORZ_VERT_POSN, (y << 16) | x); + +} + +void SHOW_CURSOR(bool is_visible) { + + if (is_visible) { + /* add cursor showing code here */ + WaitQueue(4); + while (!(inw(CRTC_VLINE_CRNT_VLINE) & CRTC_CRNT_VLINE)); + outb(GEN_TEST_CNTL, inb(GEN_TEST_CNTL) | HWCURSOR_ENABLE); + } else { + /* add cursor hiding code here */ + WaitQueue(4); + outb(GEN_TEST_CNTL, inb(GEN_TEST_CNTL) & (~HWCURSOR_ENABLE)); + } + + WaitIdleEmpty(); + + /* record for our info */ + si->cursor.is_visible = is_visible; +} diff --git a/src/add-ons/accelerants/atimach64/EngineManagment.c b/src/add-ons/accelerants/atimach64/EngineManagment.c new file mode 100644 index 0000000000..e3a4506b69 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/EngineManagment.c @@ -0,0 +1,83 @@ +#include "GlobalData.h" +#include "generic.h" + + +static engine_token ati_engine_token = { 1, B_2D_ACCELERATION, NULL }; + +uint32 ACCELERANT_ENGINE_COUNT(void) { + return 1; +} + +status_t ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et) { + /* acquire the shared benaphore */ + AQUIRE_BEN(si->engine.lock) + /* sync if required */ + if (st) SYNC_TO_TOKEN(st); + + /* return an engine token */ + *et = &ati_engine_token; + return B_OK; +} + +status_t RELEASE_ENGINE(engine_token *et, sync_token *st) { + /* update the sync token, if any */ + if (st) { + st->engine_id = et->engine_id; + st->counter = si->engine.count; + } + + /* release the shared benaphore */ + RELEASE_BEN(si->engine.lock) + return B_OK; +} + +void WAIT_ENGINE_IDLE(void) { + + // Wait until engine finishes + WaitIdleEmpty(); + // note our current possition + si->engine.last_idle = si->engine.count; +} + +status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st) { + st->engine_id = et->engine_id; + st->counter = si->engine.count; + return B_OK; +} + +status_t SYNC_TO_TOKEN(sync_token *st) { + + uint64 fifo_diff; + uint64 fifo_limit; + + /* a quick out */ + if (st->counter < si->engine.last_idle) return B_OK; + + /* the full monty */ + fifo_limit = si->engine.fifo_limit; + /* fifo_mask = si->fifo_mask;*/ + do { + /* calculate the age of the sync token */ + fifo_diff = (vuint64)(si->engine.count) - st->counter; + /* add in the number of free slots in the fifo */ + fifo_diff += (uint64)((inw(GUI_STAT) >> 16) & 0x003f); + /* + The astute observer will notice that the free slot counter + doesn't have enough bits to represent the full FIFO depth. + This means that for "recent" operations, we end up waiting + on engine idle :-( + */ +#if 1 + /* add one if the engine is idle (for when st->counter == si->engine.count) */ + if (!(inw(GUI_STAT) & 0x01)) fifo_diff++; +#endif + /* anything more than fifo_limit fifo slots ago is guaranteed done */ + /* if the engine is idle, bail out */ + } while ((fifo_diff <= fifo_limit) && (inw(GUI_STAT) & 0x01)); + + /* WAIT_ENGINE_IDLE(); */ + + si->engine.last_idle = st->counter; + return B_OK; +} + diff --git a/src/add-ons/accelerants/atimach64/GetAccelerantHook.c b/src/add-ons/accelerants/atimach64/GetAccelerantHook.c new file mode 100644 index 0000000000..d3aff93dd0 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/GetAccelerantHook.c @@ -0,0 +1,86 @@ +#include "generic.h" + +/* + +The standard entry point. Given a uint32 feature identifier, this routine +returns a pointer to the function that implements the feature. Some features +require more information than just the identifier to select the proper +function. The extra information (which is specific to the feature) is +pointed at by the void *data parameter. By default, no extra information +is available. Any extra information available to choose the function will be +noted on a case by case below. + +*/ +void * get_accelerant_hook(uint32 feature, void *data) { + switch (feature) { +/* +These definitions are out of pure lazyness. +*/ +#define HOOK(x) case B_##x: return (void *)x +#define ZERO(x) case B_##x: return (void *)0 + +/* +One of either B_INIT_ACCELERANT or B_CLONE_ACCELERANT will be requested and +subsequently called before any other hook is requested. All other feature +hook selections can be predicated on variables assigned during the accelerant +initialization process. +*/ + /* initialization */ + HOOK(INIT_ACCELERANT); + HOOK(CLONE_ACCELERANT); + + HOOK(ACCELERANT_CLONE_INFO_SIZE); + HOOK(GET_ACCELERANT_CLONE_INFO); + HOOK(UNINIT_ACCELERANT); + //HOOK(GET_ACCELERANT_DEVICE_INFO); + HOOK(ACCELERANT_RETRACE_SEMAPHORE); + + /* mode configuration */ + HOOK(ACCELERANT_MODE_COUNT); + HOOK(GET_MODE_LIST); + HOOK(PROPOSE_DISPLAY_MODE); + HOOK(SET_DISPLAY_MODE); + HOOK(GET_DISPLAY_MODE); + HOOK(GET_FRAME_BUFFER_CONFIG); + HOOK(GET_PIXEL_CLOCK_LIMITS); + HOOK(MOVE_DISPLAY); + HOOK(SET_INDEXED_COLORS); + //HOOK(GET_TIMING_CONSTRAINTS); + + HOOK(DPMS_CAPABILITIES); + HOOK(DPMS_MODE); + HOOK(SET_DPMS_MODE); + + /* cursor managment */ + HOOK(SET_CURSOR_SHAPE); + HOOK(MOVE_CURSOR); + HOOK(SHOW_CURSOR); + + /* synchronization */ + HOOK(ACCELERANT_ENGINE_COUNT); + HOOK(ACQUIRE_ENGINE); + HOOK(RELEASE_ENGINE); + HOOK(WAIT_ENGINE_IDLE); + HOOK(GET_SYNC_TOKEN); + HOOK(SYNC_TO_TOKEN); + +/* +When requesting an acceleration hook, the calling application provides a +pointer to the display_mode for which the acceleration function will be used. +Depending on the engine architecture, you may choose to provide a different +function to be used with each bit-depth. In the sample driver we return +the same function all the time. +*/ + /* 2D acceleration */ + HOOK(SCREEN_TO_SCREEN_BLIT); + HOOK(FILL_RECTANGLE); + HOOK(INVERT_RECTANGLE); + HOOK(FILL_SPAN); +#undef HOOK +#undef ZERO + } +/* +Return a null pointer for any feature we don't understand. +*/ + return 0; +} diff --git a/src/add-ons/accelerants/atimach64/GetModeInfo.c b/src/add-ons/accelerants/atimach64/GetModeInfo.c new file mode 100644 index 0000000000..9d26cd9232 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/GetModeInfo.c @@ -0,0 +1,73 @@ +#include "GlobalData.h" +#include "generic.h" + +extern uint32 calcBitsPerPixel(uint32 cs); + +/* + Return the current display mode. The only time you might return an + error is if a mode hasn't been set. +*/ +status_t GET_DISPLAY_MODE(display_mode *current_mode) { + /* easy for us, we return the last mode we set */ + *current_mode = si->dm; + return B_OK; +} + +/* + Return the frame buffer configuration information. +*/ +status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb) { + /* easy again, as the last mode set stored the info in a convienient form */ + *afb = si->fbc; + return B_OK; +} + +/* + Return the maximum and minium pixel clock limits for the specified mode. +*/ +status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high) { +/* + Note that we're not making any guarantees about the ability of the attached + display to handle pixel clocks within the limits we return. A future monitor + capablilities database will post-process this information. +*/ + uint32 total_pix = (uint32)dm->timing.h_total * (uint32)dm->timing.v_total; + uint32 clock_limit; + float i; + + /* max pixel clock is pixel depth dependant */ + switch (calcBitsPerPixel(dm->space)) { + case 32: clock_limit = si->pix_clk_max32; break; + case 15: + case 16: clock_limit = si->pix_clk_max16; break; + case 8: clock_limit = si->pix_clk_max8; break; + default: + clock_limit = 0; + } + /* printf("low %d, high %d %d \n", *low, clock_limit, si->pix_clk_max8);*/ + /* lower limit of about 48Hz vertical refresh */ + *low = (total_pix * 48L) / 1000L; + i = (total_pix * 48L) / 1000L; + + /* printf("low %d, high %d %08X \n", *low, clock_limit, dm->space);*/ + + if (*low > clock_limit) return B_ERROR; + *high = clock_limit; + return B_OK; +} + +/* + Return the semaphore id that will be used to signal a vertical retrace + occured. +*/ +sem_id ACCELERANT_RETRACE_SEMAPHORE(void) { + /* + NOTE: + The kernel driver created this for us. We don't know if the system is + using real interrupts, or if we're faking it, and we don't care. + If we choose not to support this at all, we'd just return B_ERROR here, + and the user wouldn't get any kind of vertical retrace support. + */ + /* return si->vblank;*/ + return B_ERROR; +} diff --git a/src/add-ons/accelerants/atimach64/GlobalData.c b/src/add-ons/accelerants/atimach64/GlobalData.c new file mode 100644 index 0000000000..ffd692e626 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/GlobalData.c @@ -0,0 +1,10 @@ +#include "GlobalData.h" + +int fd; +shared_info *si; +area_id shared_info_area; +vuint32 *regs; +area_id regs_area; +display_mode *atimach64_mode_list; +area_id atimach64_mode_list_area; +int accelerantIsClone; diff --git a/src/add-ons/accelerants/atimach64/GlobalData.h b/src/add-ons/accelerants/atimach64/GlobalData.h new file mode 100644 index 0000000000..1237769ebf --- /dev/null +++ b/src/add-ons/accelerants/atimach64/GlobalData.h @@ -0,0 +1,16 @@ +#if !defined(GLOBALDATA_H) +#define GLOBALDATA_H + +#include "DriverInterface.h" +#include "regmach64.h" + +extern int fd; +extern shared_info *si; +extern area_id shared_info_area; +extern vuint32 *regs; +extern area_id regs_area; +extern display_mode *atimach64_mode_list; +extern area_id atimach64_mode_list_area; +extern int accelerantIsClone; + +#endif diff --git a/src/add-ons/accelerants/atimach64/InitAccelerant.c b/src/add-ons/accelerants/atimach64/InitAccelerant.c new file mode 100644 index 0000000000..4e7420a88f --- /dev/null +++ b/src/add-ons/accelerants/atimach64/InitAccelerant.c @@ -0,0 +1,372 @@ +#include "GlobalData.h" +#include "generic.h" +#include "Mach64.h" + +#include "string.h" +#include "unistd.h" +#include "sys/types.h" +#include "sys/stat.h" +#include "fcntl.h" +#include +#include "stdio.h" + +/* defined in ProposeDisplayMode.c */ +extern status_t create_mode_list(void); +/* defined in Cursor.c */ +extern void set_cursor_colors(void); + +// Determines the amount of card memory available by seeing how far up the frame buffer +// data can be written and read back reliably. Does a paranoia check to make sure that +// It isn't just wrapping, either. +unsigned long Get_Card_Mem_Size() +{ + // Allowed sizes actually go up to 16 megs, but clip at the register window for now. + const unsigned long AllowedSizes[] = + { 0x00080000, 0x00100000, 0x00180000, 0x00200000, + 0x00280000, 0x00300000, 0x00380000, 0x00400000, + 0x00500000, 0x00600000, 0x00700000, 0x007FF800, + 0x0 }; + + unsigned long MaxMem; + unsigned long RWIndex; + int iMaxIndex, iTestIndex, iX; + unsigned long LTemp; + int IsOk; + uint32 *VramBase; + + VramBase = (uint32 *)si->framebuffer; + MaxMem = 0; // Default. + IsOk = 1; + // Step through ever-larger memory sizes, recording size if passes test and + // ignoring otherwise. + for (iMaxIndex = 0; (AllowedSizes[iMaxIndex] != 0) && IsOk; iMaxIndex++) + { + // Write test values to the linear aperature. + // Only need to do this for the farthest location, as previous locations + // already have been written to in previous passes. + RWIndex = AllowedSizes[iMaxIndex]; + RWIndex = (RWIndex - 16384) >> 2; + for (iX = 0; iX < 4096; iX++) + { + LTemp = RWIndex; + // Hash LTemp. As the parameters for the hash are prime, it should + // be extremely unlikely to get these values through a glitch, and + // the pattern only repeats at prime intervals, so aliasing shouldn't + // fool the test either. + LTemp = (263 * (LTemp % 65521) + 29) % 65521; + // Extend this to 32 bits. + LTemp |= (LTemp ^ 0x0000FFFFul) << 16; + VramBase[RWIndex] = LTemp; + RWIndex++; + } + + // Verify that all test patterns are still intact. If values written past the + // end of memory drop off the face of the frame buffer, the farthest pattern(s) + // will not be what they should be. If values written past the end of memory + // wrap, then previous patterns will be overwritten (or partly overwritten, + // as the test location at 8 megs is actually at 8 megs - 2k). + // As soon as an invalid value is detected, IsOk is set to 0, which should + // quickly terminate the test loops. + for (iTestIndex = 0; (iTestIndex <= iMaxIndex) && IsOk; iTestIndex++) + { + RWIndex = AllowedSizes[iTestIndex]; + RWIndex = (RWIndex - 16384) >> 2; + for (iX = 0; (iX < 4096) && IsOk; iX++) + { + LTemp = RWIndex; + // Hash LTemp. As the parameters for the hash are prime, it should + // be extremely unlikely to get these values through a glitch, and + // the pattern only repeats at prime intervals, so aliasing shouldn't + // fool the test either. + LTemp = (263 * (LTemp % 65521) + 29) % 65521; + // Extend this to 32 bits. + LTemp |= (LTemp ^ 0x0000FFFFul) << 16; + // Test against the value read from the frame buffer. + if (VramBase[RWIndex] != LTemp) + IsOk = 0; + RWIndex++; + } + } + + // If the test patterns check out, update MaxMem accordingly. + if (IsOk) + MaxMem = AllowedSizes[iMaxIndex]; + } + return MaxMem; +} + + + +static status_t init_common(int the_fd); + +/* Initialization code shared between primary and cloned accelerants */ +static status_t init_common(int the_fd) { + status_t result; + atimach64_get_private_data gpd; + + /* memorize the file descriptor */ + fd = the_fd; + /* set the magic number so the driver knows we're for real */ + gpd.magic = ATIMACH64_PRIVATE_DATA_MAGIC; + /* contact driver and get a pointer to the registers and shared data */ + result = ioctl(fd, ATIMACH64_GET_PRIVATE_DATA, &gpd, sizeof(gpd)); + + if (result != B_OK) goto error0; + + /* clone the shared area for our use */ + shared_info_area = clone_area("ATIMACH64 shared info", (void **)&si, B_ANY_ADDRESS, + B_READ_AREA | B_WRITE_AREA, gpd.shared_info_area); + if (shared_info_area < 0) { + result = shared_info_area; + goto error0; + } + + /* all done */ + goto error0; + +error0: + return result; +} + +/* Clean up code shared between primary and cloned accelrants */ +static void uninit_common(void) { + /* release the memory mapped registers */ + /* delete_area(regs_area); */ + /* a little cheap paranoia */ + regs = 0; + /* release our copy of the shared info from the kernel driver */ + delete_area(shared_info_area); + /* more cheap paranoia */ + si = 0; +} + +/* +Initialize the accelerant. the_fd is the file handle of the device (in +/dev/graphics) that has been opened by the app_server (or some test harness). +We need to determine if the kernel driver and the accelerant are compatible. +If they are, get the accelerant ready to handle other hook functions and +report success or failure. +*/ +status_t INIT_ACCELERANT(int the_fd) { + status_t result; + + /* note that we're the primary accelerant (accelerantIsClone is global) */ + accelerantIsClone = 0; + + /* do the initialization common to both the primary and the clones */ + result = init_common(the_fd); + + /* bail out if the common initialization failed */ + if (result != B_OK) goto error0; + + /* + If there is a possiblity that the kernel driver will recognize a card that + the accelerant can't support, you should check for that here. Perhaps some + odd memory configuration or some such. + */ + + /* + This is a good place to go and initialize your card. The details are so + device specific, we're not even going to pretend to provide you with sample + code. If this fails, we'll have to bail out, cleaning up the resources + we've already allocated. + */ + /* call the device specific init code */ + if (si->mem_size != Get_Card_Mem_Size()){ + result = B_ERROR; + } + + mach64InitAperture(); + mach64ResetEngine(); + WaitIdleEmpty(); + + /* Disable all interrupts */ + outw(CRTC_INT_CNTL, 0); + + WaitIdleEmpty(); + + /* bail out if it failed */ + if (result != B_OK) goto error1; + + /* + Now would be a good time to figure out what video modes your card supports. + We'll place the list of modes in another shared area so all of the copies + of the driver can see them. The primary copy of the accelerant (ie the one + initialized with this routine) will own the "one true copy" of the list. + Everybody else get's a read-only clone. + */ + + result = create_mode_list(); + if (result != B_OK) goto error2; + + /* + Initialize the frame buffer and cursor pointers. Most newer video cards + have integrated the DAC into the graphics engine, and so the cursor shape + is stored in the frame buffer RAM. Also, newer cards tend not to have as + many restrictions about the placement of the start of the frame buffer in + frame buffer RAM. If you're supporting an older card with frame buffer + positioning restrictions, or one without an integrated DAC, you'll have to + change this accordingly. + */ + + /* + Put the cursor at the start of the frame buffer. The typical 64x64 4 color + (black, white, transparent, inverse) takes up 1024 bytes of RAM. + */ + si->cursor.data = (uint8 *)si->framebuffer; + + /* Initialize cursor as transparent */ + memset(si->cursor.data, 0xaa, 1024); + + /* Initialize the rest of the cursor information while we're here */ + si->cursor.width = 0; + si->cursor.height = 0; + si->cursor.hot_x = 0; + si->cursor.hot_y = 0; + si->cursor.x = 0; + si->cursor.y = 0; + + /* Tell the hardware all the cursor info */ + + outw(CUR_OFFSET, 0x00000000); /* Where it is in memory */ + outw(CUR_HORZ_VERT_POSN, 0x00000000); /* Position in screen */ + outw(CUR_HORZ_VERT_OFF, 0x00000000); /* Hot x,y */ + + /* + Put the frame buffer immediately following the cursor data. We store this + info in a frame_buffer_config structure to make it convienient to return + to the app_server later. + */ + si->fbc.frame_buffer = (void *)(((char *)si->framebuffer) + 1024); + si->fbc.frame_buffer_dma = (void *)(((char *)si->framebuffer_pci) + 1024); + + /* init the shared semaphore */ + INIT_BEN(si->engine.lock); + /* initialize the engine synchronization variables */ + + /* count of issued parameters or commands */ + si->engine.last_idle = si->engine.count = 0; + + /* bail out if something failed */ + if (result != B_OK) goto error3; + + /* set the cursor colors. You may or may not have to do this, depending + on the device. */ + set_cursor_colors(); + + /* ensure cursor state */ + SHOW_CURSOR(false); + /* a winner! */ + result = B_OK; + goto error0; + +error3: + /* free up the benaphore */ + DELETE_BEN(si->engine.lock); + +error2: + /* + Clean up any resources allocated in your device specific initialization + code. + */ + +error1: + /* + Initialization failed after init_common() succeeded, so we need to clean + up before quiting. + */ + uninit_common(); + +error0: + return result; +} + +/* +Return the number of bytes required to hold the information required +to clone the device. +*/ +ssize_t ACCELERANT_CLONE_INFO_SIZE(void) { + /* + Since we're passing the name of the device as the only required + info, return the size of the name buffer + */ + return MAX_ATIMACH64_DEVICE_NAME_LENGTH; +} + + +/* +Return the info required to clone the device. void *data points to +a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length. +*/ +void GET_ACCELERANT_CLONE_INFO(void *data) { + atimach64_device_name dn; + status_t result; + + /* call the kernel driver to get the device name */ + dn.magic = ATIMACH64_PRIVATE_DATA_MAGIC; + /* store the returned info directly into the passed buffer */ + dn.name = (char *)data; + result = ioctl(fd, ATIMACH64_DEVICE_NAME, &dn, sizeof(dn)); +} + +/* +Initialize a copy of the accelerant as a clone. void *data points to +a copy of the data returned by GET_ACCELERANT_CLONE_INFO(). +*/ +status_t CLONE_ACCELERANT(void *data) { + status_t result; + char path[MAXPATHLEN]; + + /* the data is the device name */ + strcpy(path, "/dev"); + strcat(path, (const char *)data); + /* open the device, the permissions aren't important */ + fd = open(path, B_READ_WRITE); + if (fd < 0) { + result = fd; + goto error0; + } + + /* note that we're a clone accelerant */ + accelerantIsClone = 1; + + /* call the shared initialization code */ + result = init_common(fd); + + /* bail out if the common initialization failed */ + if (result != B_OK) goto error1; + + /* get shared area for display modes */ + result = atimach64_mode_list_area = clone_area( + "ATIMACH64 cloned display_modes", + (void **)&atimach64_mode_list, + B_ANY_ADDRESS, + B_READ_AREA, + si->mode_area + ); + if (result < B_OK) goto error2; + + /* all done */ + result = B_OK; + goto error0; + +error2: + /* free up the areas we cloned */ + uninit_common(); +error1: + /* close the device we opened */ + close(fd); +error0: + return result; +} + +void UNINIT_ACCELERANT(void) { + /* free our mode list area */ + delete_area(atimach64_mode_list_area); + /* paranoia */ + atimach64_mode_list = 0; + /* release our cloned data */ + uninit_common(); + /* close the file handle ONLY if we're the clone */ + if (accelerantIsClone) close(fd); +} diff --git a/src/add-ons/accelerants/atimach64/Jamfile b/src/add-ons/accelerants/atimach64/Jamfile new file mode 100644 index 0000000000..bb2b564fde --- /dev/null +++ b/src/add-ons/accelerants/atimach64/Jamfile @@ -0,0 +1,21 @@ +SubDir OBOS_TOP src add-ons accelerants atimach64 ; + +UsePrivateHeaders graphics ; +UsePrivateHeaders [ FDirName graphics atimach64 ] ; + +Addon atimach64.accelerant : accelerants : + Acceleration.c + Cursor.c + EngineManagment.c + GetAccelerantHook.c + GlobalData.c + GetModeInfo.c + InitAccelerant.c + Mach64.c + Mach64fifo.c + ProposeDisplayMode.c + SetDisplayMode.c +; + +Depends atimach64.accelerant : atimach64.driver ; + diff --git a/src/add-ons/accelerants/atimach64/Mach64.c b/src/add-ons/accelerants/atimach64/Mach64.c new file mode 100644 index 0000000000..9013aabcc1 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/Mach64.c @@ -0,0 +1,447 @@ +/* All this code has been reversed engineered from Xfree86 Project :-) + + Copyright 1999 by + + Rene MacKinney + + 7.May.99 + +*/ + +//------------------------------------------------------------------------ +/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/mach64/mach64.c,v 3.62.2.15 19 +98/10/18 20:42:04 hohndel Exp $ */ +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * Copyright 1993,1994,1995,1996,1997 by Kevin E. Martin, Chapel Hill, North Car +olina. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL, KEVIN E. MARTIN, AND RICKARD E. FAITH DISCLAIM ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY + * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Thomas Roell, roell@informatik.tu-muenchen.de + * + * Rewritten for the 8514/A by Kevin E. Martin (martin@cs.unc.edu) + * Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu) + * Rewritten for the Mach32 by Kevin E. Martin (martin@cs.unc.edu) + * Rewritten for the Mach64 by Kevin E. Martin (martin@cs.unc.edu) + * Support for the Mach64 CT added by David Dawes (dawes@XFree86.org) + * + */ +/* $XConsortium: mach64.c /main/34 1996/10/28 04:46:47 kaleb $ */ + + +//--------------------------------------------------------------------------- + +#include + +#include "GlobalData.h" +#include "generic.h" +#include "Mach64fifo.h" +#include "Mach64.h" + + +/* + * mach64FIFOdepth -- + * Calculates the correct FIFO depth for the Mach64 depending on the + * color depth and clock selected. + */ +int mach64FIFOdepth(cdepth, clock, width) + int cdepth; + int clock; + int width; +{ + int fifo_depth; + + if (si->device_id == MACH64_VT_ID) { + if (si->revision == 0x48) { /* VTA4 */ + fifo_depth = mach64FIFOdepthVTA4(cdepth, clock, width); + } else { /* VTA3 */ + fifo_depth = mach64FIFOdepthVTA3(cdepth, clock, width); + } + } else if (si->device_id == MACH64_GT_ID) { + fifo_depth = mach64FIFOdepthGT(cdepth, clock, width); + } else if (si->device_id == MACH64_CT_ID && si->revision == 0x0a) { + /* CT-D has a larger FIFO and thus requires special code */ + fifo_depth = mach64FIFOdepthCTD(cdepth, clock, width); + } else if (si->device_id == MACH64_CT_ID || + si->device_id == MACH64_ET_ID) { + fifo_depth = mach64FIFOdepthCT(cdepth, clock, width); + } else { + fifo_depth = mach64FIFOdepthDefault(cdepth, clock, width); + } + + return(fifo_depth); +} + +/* + * mach64ProgramClkMach64CT -- + * + */ +void mach64ProgramClkMach64CT(clkCntl, MHz100) + int clkCntl; + int MHz100; +{ + char old_crtc_ext_disp; +#ifdef DEBUG + extern void mach64PrintCTPLL(); +#endif + int M, N, P, R; + float Q; + int postDiv; + int mhz100 = MHz100; + unsigned char tmp1, tmp2; + int ext_div = 0; + float current_dot_clock; + + old_crtc_ext_disp = inb(CRTC_GEN_CNTL+3); + outb(CRTC_GEN_CNTL+3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24)); + + M = si->RefDivider; + R = si->RefFreq; + + if (clkCntl > 3) clkCntl = 3; + + if (mhz100 < si->MinFreq) mhz100 = si->MinFreq; + if (mhz100 > si->MaxFreq) mhz100 = si->MaxFreq; + + Q = (mhz100 * M)/(2.0 * R); + + if (false) { /* mach64HasDSP) { */ + if (Q > 255) { + /* printf("mach64ProgramClkMach64CT: Warning: Q > 255\n");*/ + Q = 255; + P = 0; + postDiv = 1; + } else if (Q > 127.5) { + P = 0; + postDiv = 1; + } else if (Q > 85) { + P = 1; + postDiv = 2; + } else if (Q > 63.75) { + P = 0; + postDiv = 3; + ext_div = 1; + } else if (Q > 42.5) { + P = 2; + postDiv = 4; + } else if (Q > 31.875) { + P = 2; + postDiv = 6; + ext_div = 1; + } else if (Q > 21.25) { + P = 3; + postDiv = 8; + } else if (Q >= 10.6666666667) { + P = 3; + postDiv = 12; + ext_div = 1; + } else { + /* printf("mach64ProgramClkMach64CT: Warning: Q < 10.66666667\n");*/ + P = 3; + postDiv = 12; + ext_div = 1; + } + } else { + if (Q > 255) { + /* printf("mach64ProgramClkMach64CT: Warning: Q > 255\n");*/ + Q = 255; + P = 0; + } + else if (Q > 127.5) + P = 0; + else if (Q > 63.75) + P = 1; + else if (Q > 31.875) + P = 2; + else if (Q >= 16) + P = 3; + else { + /* printf("mach64ProgramClkMach64CT: Warning: Q < 16\n");*/ + P = 3; + } + postDiv = 1 << P; + } + N = (int)(Q * postDiv + 0.5); + + current_dot_clock = (2.0 * R * N)/(M * postDiv); + +#ifdef DEBUG_HARNESS + printf("Q = %f N = %d P = %d, postDiv = %d R = %d M = %d\n", Q, N, P, postDiv, R, M); + printf("New freq: %.2f\n", (double)((2 * R * N)/(M * postDiv)) / 100.0); +#endif + + outb(CLOCK_CNTL + 1, PLL_VCLK_CNTL << 2); +#ifdef DEBUG_HARNESS + printf("CLOCK_CNTL + 1 = 0x%08x\n",PLL_VCLK_CNTL << 2); +#endif + tmp1 = inb(CLOCK_CNTL + 2); + outb(CLOCK_CNTL + 1, (PLL_VCLK_CNTL << 2) | PLL_WR_EN); + outb(CLOCK_CNTL + 2, tmp1 | 0x04); + outb(CLOCK_CNTL + 1, VCLK_POST_DIV << 2); + tmp2 = inb(CLOCK_CNTL + 2); + outb(CLOCK_CNTL + 1, ((VCLK0_FB_DIV + clkCntl) << 2) | PLL_WR_EN); + outb(CLOCK_CNTL + 2, N); + outb(CLOCK_CNTL + 1, (VCLK_POST_DIV << 2) | PLL_WR_EN); + outb(CLOCK_CNTL + 2, + (tmp2 & ~(0x03 << (2 * clkCntl))) | (P << (2 * clkCntl))); + outb(CLOCK_CNTL + 1, (PLL_VCLK_CNTL << 2) | PLL_WR_EN); + outb(CLOCK_CNTL + 2, tmp1 & ~0x04); + + if (false) { /* mach64HasDSP) { */ + outb(CLOCK_CNTL + 1, PLL_XCLK_CNTL << 2); + tmp1 = inb(CLOCK_CNTL + 2); + outb(CLOCK_CNTL + 1, (PLL_XCLK_CNTL << 2) | PLL_WR_EN); + if (ext_div) + outb(CLOCK_CNTL + 2, tmp1 | (1 << (clkCntl + 4))); + else + outb(CLOCK_CNTL + 2, tmp1 & ~(1 << (clkCntl + 4))); + } + + snooze(5000); + + (void)inb(DAC_REGS); /* Clear DAC Counter */ + outb(CRTC_GEN_CNTL+3, old_crtc_ext_disp); + + return; +} + +/* + * CalcCRTCRegs -- + * Calculate appropiate values for CRTC Registers + */ +void +CalcCRTCRegs(crtcRegs, mode) + mach64CRTCRegPtr crtcRegs; + display_mode *mode; +{ + int h_pol = (mode->timing.flags & B_POSITIVE_HSYNC) ? 1 : 0; + int v_pol = (mode->timing.flags & B_POSITIVE_VSYNC) ? 1 : 0; + + /* Register CRTC_H_TOTAL_DISP + bits 23-16 Horizontal total visible in character clocks (8 pixel units) + bits 7-0 Horizontal display end in character clocks + */ + crtcRegs->h_total_disp = (((mode->timing.h_display >> 3) - 1) << 16) | + ((mode->timing.h_total >> 3) - 1); + + /* Register CRTC_H_SYNC_STRT_WID + bits 21 Horizontal sync polarity + bits 20-16 Horizontal sync width in character clocks + bits 10-8 Horizontal sync start delay in pixels + bits 7-0 Horizontal sync start in character clocks + */ + crtcRegs->h_sync_strt_wid = h_pol << 21 | + (((mode->timing.h_sync_end - mode->timing.h_sync_start) >> 3) << 16) | + /* ((mode->timing.h_sync_start % 8) << 8) |*/ + ((mode->timing.h_sync_start >> 3) - 1); + + /* Register CRTC_V_TOTAL_DISP + bits 23-16 Vertical total visible in lines + bits 7-0 Vertical display end in lines + */ + crtcRegs->v_total_disp = ((mode->timing.v_display - 1) << 16) | + (mode->timing.v_total - 1); + + /* Register CRTC_V_SYNC_STRT_WID + bits 21 Vertical sync polarity + bits 20-16 Vertical sync width in lines + bits 10-0 Vertical sync start in lines + */ + crtcRegs->v_sync_strt_wid = v_pol << 21 | + ((mode->timing.v_sync_end - mode->timing.v_sync_start) << 16) | + (mode->timing.v_sync_start - 1); + + switch (mode->space & 0x0fff) { + case B_CMAP8: + crtcRegs->color_depth = CRTC_PIX_WIDTH_8BPP; + break; + case B_RGB15: + crtcRegs->color_depth = CRTC_PIX_WIDTH_15BPP; + break; + case B_RGB16: + crtcRegs->color_depth = CRTC_PIX_WIDTH_16BPP; + break; + case B_RGB32: + crtcRegs->color_depth = CRTC_PIX_WIDTH_32BPP; + break; + default: + } + + crtcRegs->crtc_gen_cntl = 0; + if (mode->timing.flags & B_TIMING_INTERLACED) + crtcRegs->crtc_gen_cntl |= CRTC_INTERLACE_EN; + + + crtcRegs->clock_cntl = 0x03; /* Hack */ + crtcRegs->dot_clock = mode->timing.pixel_clock / 10; + + crtcRegs->fifo_v1 = mach64FIFOdepth(crtcRegs->color_depth, + crtcRegs->dot_clock, mode->timing.h_display); + + + + +} + +/* + * SetCRTCRegs + * Write values to the CRTC Registers */ +void +SetCRTCRegs(crtcRegs, mode) + mach64CRTCRegPtr crtcRegs; + display_mode *mode; +{ + int crtcGenCntl; + uint32 offset; + + WaitIdleEmpty(); + crtcGenCntl = inw(CRTC_GEN_CNTL); + outw(CRTC_GEN_CNTL, crtcGenCntl & ~(CRTC_EXT_EN | CRTC_LOCK_REGS)); + + /* Program the clock chip */ + mach64ProgramClkMach64CT(0x03, crtcRegs->dot_clock); + + + /* Horizontal CRTC registers */ + outw(CRTC_H_TOTAL_DISP, crtcRegs->h_total_disp); + outw(CRTC_H_SYNC_STRT_WID, crtcRegs->h_sync_strt_wid); + + /* Vertical CRTC registers */ + outw(CRTC_V_TOTAL_DISP, crtcRegs->v_total_disp); + outw(CRTC_V_SYNC_STRT_WID, crtcRegs->v_sync_strt_wid); + + /* Clock select register */ + outw(CLOCK_CNTL, crtcRegs->clock_cntl | CLOCK_STROBE); + + /* Zero overscan register to insure proper color */ + /* outw(OVR_CLR, 0); + outw(OVR_WID_LEFT_RIGHT, 0); + outw(OVR_WID_TOP_BOTTOM, 0); + */ + /* Set the offset and width of the display + We could just use the offset value we already know (1024) but this + will deal with any changes + */ + offset = (si->fbc.frame_buffer - si->framebuffer) >> 3; + + outw(CRTC_OFF_PITCH, ((mode->virtual_width >> 3) << 22) | offset); + outw(DST_OFF_PITCH, ((mode->virtual_width >> 3) << 22) | offset); + outw(SRC_OFF_PITCH, ((mode->virtual_width >> 3) << 22) | offset); + + + + /* Display control register -- this one turns on the display */ + + outw(CRTC_GEN_CNTL, + (crtcGenCntl & 0xff0000ff & + ~(CRTC_PIX_BY_2_EN | CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN | + CRTC_HSYNC_DIS | CRTC_VSYNC_DIS)) | + (crtcRegs->crtc_gen_cntl & ~CRTC_PIX_BY_2_EN) | + crtcRegs->color_depth | + (((crtcRegs->fifo_v1 & 0x0f) << 16) | + CRTC_EXT_DISP_EN | CRTC_EXT_EN)); + + /* printf(" crtcGenCntl 0x%08x\n", (crtcGenCntl & 0xff0000ff & + ~(CRTC_PIX_BY_2_EN | CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN | + CRTC_HSYNC_DIS | CRTC_VSYNC_DIS)) | + (crtcRegs->crtc_gen_cntl & ~CRTC_PIX_BY_2_EN) | + crtcRegs->color_depth | + (((crtcRegs->fifo_v1 & 0x0f) << 16) | + CRTC_EXT_DISP_EN | CRTC_EXT_EN));*/ + + + /* Set the DAC for the currect mode */ + /* mach64SetRamdac(crtcRegs->color_depth, TRUE, crtcRegs->dot_clock); + */ + WaitIdleEmpty(); +} + +/* + * mach64InitAperture -- + * Initialize the aperture for the Mach64. + */ +void mach64InitAperture() +{ + ulong apaddr = (ulong) si->framebuffer_pci; + + outw(CONFIG_CNTL, ((apaddr/(4*1024*1024)) << 4) | 2); + +} + +/* + * mach64ResetEngine -- + * Resets the GUI engine and clears any FIFO errors. + */ +void mach64ResetEngine() +{ + int temp; + + /* Ensure engine is not locked up by clearing any FIFO errors */ + outw(BUS_CNTL, inw(BUS_CNTL) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK); + + /* Reset engine */ + temp = inw(GEN_TEST_CNTL); + outw(GEN_TEST_CNTL, temp & ~GUI_ENGINE_ENABLE); + + outw(GEN_TEST_CNTL, temp | GUI_ENGINE_ENABLE); + + WaitIdleEmpty(); +} + + + +void +InitRAMDAC(uint32 colorDepth, uint32 flags) +{ + int count; + uint8 val; + + WaitIdleEmpty(); + + /* Initialize Acceleration Mode */ + + outb(CRTC_GEN_CNTL+3, ((CRTC_EXT_DISP_EN | CRTC_EXT_EN) >> 24)); + + switch(colorDepth){ + case 8: + val = inb(DAC_CNTL+1); + if (flags & B_8_BIT_DAC) + outb(DAC_CNTL + 1, val | 0x01); + else + outb(DAC_CNTL + 1, val & ~0x01); + break; + case 15: + case 16: + case 24: + case 32: + val = inb(DAC_CNTL + 1); + outb(DAC_CNTL + 1, val | 0x01); + outb(DAC_CNTL + 2, 0xff); + outb(DAC_REGS, 0x00); + for(count = 0; count < 256; count ++) { + outb(DAC_REGS+1, count); + outb(DAC_REGS+1, count); + outb(DAC_REGS+1, count); + } + + break; + } + +} diff --git a/src/add-ons/accelerants/atimach64/Mach64.h b/src/add-ons/accelerants/atimach64/Mach64.h new file mode 100644 index 0000000000..dc551550b9 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/Mach64.h @@ -0,0 +1,5 @@ +extern void mach64InitAperture(); +extern void mach64ResetEngine(); +extern void CalcCRTCRegs(mach64CRTCRegPtr, display_mode *); +extern void SetCRTCRegs(mach64CRTCRegPtr, display_mode *); +void InitRAMDAC(uint32, uint32); diff --git a/src/add-ons/accelerants/atimach64/Mach64fifo.c b/src/add-ons/accelerants/atimach64/Mach64fifo.c new file mode 100644 index 0000000000..60bec9af83 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/Mach64fifo.c @@ -0,0 +1,1738 @@ +/* + * Copyright 1996 by Kevin E. Martin, Chapel Hill, North Carolina. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Kevin + * E. Martin not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Kevin E. Martin makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * KEVIN E. MARTIN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/mach64/mach64fifo.c,v 3.1 1996/12/28 08:14:40 dawes Exp $ */ + +#include "GlobalData.h" +#include "generic.h" + +#define MAX_CDEPTH 6 +#define MAX_DOTCLOCKS 14 + +typedef struct { + short dotclock; + unsigned char fifo_val; +} mach64FIFOTable; + + +static unsigned char defaultFIFOVals[] = { + 0x02, 0x0c, 0x02, 0x06, 0x02, 0x0e, /* 8 bpp */ + 0x02, 0x0e, 0x02, 0x0e, 0x02, 0x0e, /* 16 bpp */ + 0x02, 0x0e, 0x02, 0x0e, 0x02, 0x0e, /* 24 bpp */ + 0x02, 0x0e, 0x02, 0x0e, 0x02, 0x0e /* 32 bpp */ +}; + +static unsigned char CT_FIFOVals[] = { + /* 640x480 */ + 0x04, 0x0c, 0x04, 0x08, 0x09, 0x0f, /* 8 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x08, 0x0f, /* 16 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x08, 0x0f, /* 24 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x08, 0x0f, /* 32 bpp */ + /* 800x600 */ + 0x04, 0x0c, 0x04, 0x08, 0x08, 0x0f, /* 8 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x08, 0x0f, /* 16 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f, /* 24 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f, /* 32 bpp */ + /* 1024x768 */ + 0x04, 0x0c, 0x04, 0x08, 0x08, 0x0f, /* 8 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f, /* 16 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f, /* 24 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f, /* 32 bpp */ + /*1280x1024 */ + 0x04, 0x0c, 0x04, 0x08, 0x0e, 0x0f, /* 8 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f, /* 16 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f, /* 24 bpp */ + 0x04, 0x0e, 0x04, 0x0e, 0x0e, 0x0f /* 32 bpp */ +}; + +static mach64FIFOTable VTA3_SDRAM_1M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 3600, 0x04}, { 4400, 0x06}, { 6800, 0x06}, { 9000, 0x08}, + {10500, 0x0a}, {24000, 0x0c} }, /* 8bpp */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0e} }, /* 15bpp */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0e} }, /* 16bpp */ + { { 2200, 0x08}, { 2600, 0x08}, { 3300, 0x0a}, { 3600, 0x0c}, + { 4000, 0x0e}, {24000, 0x0e} }, /* 24bpp */ + { {24000, 0x08} } /* 32bpp */ +}; + +static mach64FIFOTable VTA3_SDRAM_2M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 4000, 0x04}, { 5700, 0x06}, { 9400, 0x08}, {11200,0x0c}, + {24000, 0x0e} }, /* 8bpp */ + { { 2600, 0x06}, { 4200, 0x08}, { 4600, 0x0a}, { 6400, 0x0c}, + {24000, 0x0e} }, /* 15bpp */ + { { 2600, 0x06}, { 4200, 0x08}, { 4600, 0x0a}, { 6400, 0x0c}, + {24000, 0x0e} }, /* 16bpp */ + { { 2600, 0x0a}, { 3800, 0x0c}, { 4000, 0x0c}, { 4500, 0x28}, + {24000, 0x2c} }, /* 24bpp */ + { { 2200, 0x0a}, { 3000, 0x0c}, { 3400, 0x0e}, {24000, 0x0e} } /* 32bpp */ +}; + +static mach64FIFOTable VTA3_SDRAM_1M_6300_5[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x08} }, + { { 3800, 0x04}, { 4400, 0x06}, { 6600, 0x06}, { 9000, 0x08}, + {24000, 0x0a} }, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, { 6900, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, { 6900, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 2600, 0x0a}, { 3400, 0x0c}, { 4200, 0x0e}, + { 4600, 0x0e}, {24000, 0x0e} }, + { {24000, 0x06} } + }; + +static mach64FIFOTable VTA3_SDRAM_2M_6300_5[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, + { { 3000, 0x04}, { 4000, 0x06}, { 6000, 0x08}, { 9400, 0x0a}, + {10000, 0x0c}, {11200, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3500, 0x08}, { 4400, 0x0a}, { 6400, 0x0e}, + { 6800, 0x0e}, { 8200, 0x0e}, {10100, 0x0e}, {11100, 0x0e}, + {13100, 0x0e}, {13600, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3500, 0x08}, { 4400, 0x0a}, { 6400, 0x0e}, + { 6800, 0x0e}, { 8200, 0x0e}, {10100, 0x0e}, {11100, 0x0e}, + {13100, 0x0e}, {13600, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x0a}, { 4200, 0x0c}, { 4500, 0x28}, { 5200, 0x2c}, + { 5700, 0x2c}, { 6600, 0x2c}, { 6800, 0x2c}, { 7600, 0x2c}, + { 8200, 0x2c}, {10100, 0x2c}, {11100, 0x2c}, {12200, 0x2c}, + {24000, 0x2c} }, + { { 2000, 0x0a}, { 3000, 0x0c}, { 3400, 0x0e}, { 4100, 0x2e}, + { 4600, 0x2e}, { 5200, 0x2e}, { 5700, 0x2e}, { 6600, 0x2e}, + { 7000, 0x2e}, { 7600, 0x2e}, { 7900, 0x2e}, { 8200, 0x2e}, + {24000, 0x2e} } +}; + +static mach64FIFOTable VTA3_SDRAM_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 3600, 0x04}, { 4400, 0x06}, { 7500, 0x06}, { 8200, 0x08}, + {24000,0x0a}}, /* 8bpp */ + { { 2600, 0x06}, { 3200, 0x06}, { 3600, 0x08}, { 4000, 0x0a}, + { 5800, 0x0c}, { 8000, 0x0e}, {24000, 0x0e} }, /* 15bpp */ + { { 2600, 0x06}, { 3200, 0x06}, { 3600, 0x08}, { 4000, 0x0a}, + { 5800, 0x0c}, { 8000, 0x0e}, {24000, 0x0e} }, /* 16bpp */ + { { 2000, 0x08}, { 2600, 0x08}, { 3200, 0x0a}, { 3700, 0x0c}, + { 4200, 0x0c}, {24000, 0x0e} }, /* 24bpp */ + { {24000, 0x06} } /* 32bpp */ +}; + +static mach64FIFOTable VTA3_SDRAM_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, /* 4 bpp */ + { { 4000, 0x04}, { 5800, 0x06}, { 8200, 0x08}, {10000, 0x0a}, + {11200, 0x0c}, {24000, 0x0e}}, /* 8bpp */ + { { 2600, 0x06}, { 4000, 0x08}, { 5100, 0x0a}, { 5800, 0x0c}, + {24000, 0x0e} }, /* 15bpp */ + { { 2600, 0x06}, { 4000, 0x08}, { 5100, 0x0a}, { 5800, 0x0c}, + {24000, 0x0e} }, /* 16bpp */ + { { 2600, 0x0a}, { 4000, 0x0c}, { 4500, 0x28}, {24000, 0x2c} }, /* 24bpp */ + { { 2600, 0x0a}, { 3600, 0x0e}, {24000, 0x2e} } /* 32bpp */ +}; + +static mach64FIFOTable VTA3_SDRAM_1M_6700[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, { 8000, 0x08}, + {24000, 0x08} }, + { { 3800, 0x04}, { 4400, 0x06}, { 7800, 0x06}, { 9000, 0x08}, + {24000, 0x0a}}, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0c} }, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0c} }, + { { 2000, 0x06}, { 2600, 0x06}, { 3400, 0x0a}, { 4100, 0x0c}, + {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA3_SDRAM_2M_6700[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x04}, { 9400, 0x06}, {11200, 0x08}, {24000, 0x08} }, + { { 4400, 0x04}, { 6600, 0x06}, { 9400, 0x08}, {10000, 0x0a}, + {11200, 0x0c}, {14000, 0x0c}, {24000, 0x0c}}, + { { 3400, 0x06}, { 4200, 0x08}, { 5400, 0x0a}, { 6600, 0x0c}, + { 8000, 0x0e}, {24000, 0x0e} }, + { { 3400, 0x06}, { 4200, 0x08}, { 5400, 0x0a}, { 6600, 0x0c}, + { 8000, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3000, 0x08}, { 3300, 0x0a}, { 4200, 0x0c}, + { 4600, 0x0c}, {24000, 0x2c} }, + { { 3000, 0x0a}, { 3400, 0x0c}, { 3800, 0x0e}, { 5200, 0x0e}, } +}; + +static mach64FIFOTable VTA3_EDO_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 4800, 0x06}, { 5400, 0x06}, + { 6800, 0x0a}, { 7700, 0x0a}, { 9000, 0x0a}, {11000, 0x0c}, + {24000,0x0e}}, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, {4400, 0x0a}, + { 4800, 0x0e}, {5500, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, {4400, 0x0a}, + { 4800, 0x0e}, {5500, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x0a}, { 3000, 0x0a}, {3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } +}; + +static mach64FIFOTable VTA3_EDO_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11100, 0x0c}, {13000, 0x0c}, {14000, 0x0c}, + {24000, 0x0e}}, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4100, 0x0a}, + { 4500, 0x0c}, { 5200, 0x0e}, { 5700, 0x2a}, { 6800, 0x2a}, + {24000, 0x2a} }, + { { 3000, 0x0a}, { 3500, 0x0e}, {4200, 0x0e}, { 4600, 0x2a}, + { 5200, 0x2a}, {24000, 0x2a} } +}; + +static mach64FIFOTable VTA3_EDO_1M_6700_6[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 5400, 0x06}, { 7700, 0x0a}, + { 9000, 0x0a}, {10500, 0x0c}, {24000, 0x0e}}, + { { 2000, 0x06}, { 3000, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 4800, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 4800, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA3_EDO_2M_6700_6[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11300, 0x0c}, {14000, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4200, 0x0a}, + { 4500, 0x0c}, { 5200, 0x0c}, {24000, 0x2c} }, + { { 2000, 0x0a}, { 3000, 0x0a}, { 3500, 0x0c}, { 4200, 0x0e}, + {24000, 0x2a} } +}; + +static mach64FIFOTable VTA3_EDO_1M_6700_7[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4200, 0x04}, { 6400, 0x06}, { 9000, 0x0a}, {24000, 0x0c} }, + { { 3800, 0x08}, { 6400, 0x0a}, { 7000, 0x0c}, { 9000, 0x0c}, + {24000, 0x0c}}, + { { 3800, 0x0a}, { 4800, 0x0c}, { 5600, 0x0e}, {24000, 0x0e} }, + { { 3800, 0x0a}, { 4800, 0x0c}, { 5600, 0x0e}, {24000, 0x0e} }, + { { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA3_EDO_2M_6700_7[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x02}, { 7000, 0x04}, {10200, 0x06}, {24000, 0x0a} }, + { { 5200, 0x06}, { 6400, 0x08}, { 7000, 0x0a}, { 7900, 0x0c}, + { 8200, 0x0c}, {10800, 0x0c}, {13000, 0x0c}, {24000, 0x0c} }, + { { 3000, 0x06}, { 3800, 0x08}, { 4200, 0x0a}, { 5200, 0x0a}, + { 6600, 0x0c}, { 7600, 0x0c}, { 8200, 0x0c}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3800, 0x08}, { 4200, 0x0a}, { 5200, 0x0c}, + { 6600, 0x0c}, { 7600, 0x0c}, { 8200, 0x0c}, {24000, 0x0e} }, + { { 3000, 0x0a}, { 3400, 0x0a}, { 3600, 0x0a}, { 4400, 0x0c}, + { 5200, 0x0c} }, + { { 3400, 0x0c}, { 5200, 0x0c} } +}; + +static mach64FIFOTable VTA3_PSEUDO_1M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 5400, 0x06}, { 7700, 0x0a}, + { 9000, 0x0a}, {12000, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 4400, 0x0a}, { 4800, 0x0e}, + { 5500, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 4400, 0x0a}, { 4800, 0x0e}, + { 5500, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } +}; + +static mach64FIFOTable VTA3_PSEUDO_2M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11300, 0x0c}, {12700, 0x0c}, {14000, 0x0c}, + {24000, 0x0e} }, /* 8bpp */ + { { 2200, 0x06}, { 3400, 0x06}, { 4200, 0x0a}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 15bpp */ + { { 2200, 0x06}, { 3400, 0x06}, { 4200, 0x0a}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 16bpp */ + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4200, 0x0a}, + { 4500, 0x0c}, { 5200, 0x28}, {24000, 0x2a} }, /* 24bpp */ + { { 3000, 0x0a}, { 3500, 0x0e}, { 4200, 0x0e}, {24000, 0x2a} } /* 32bpp */ +}; + +static mach64FIFOTable VTA3_PSEUDO_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 4800, 0x06}, { 5400, 0x06}, + { 6800, 0x0a}, { 7700, 0x0a}, { 9000, 0x0a}, {11100, 0x0c}, + {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } +}; + +static mach64FIFOTable VTA3_PSEUDO_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11100, 0x0c}, {13000, 0x0c}, {14000, 0x0c}, + {24000, 0x0e} }, + { { 2200, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4100, 0x0a}, + { 4500, 0x0c}, { 5200, 0x0e}, { 5700, 0x2a}, { 6800, 0x2a}, + {24000, 0x2a} }, + { { 3000, 0x0a}, { 3500, 0x0e}, { 4200, 0x0e}, { 4600, 0x2a}, + { 5200, 0x2a}, {24000, 0x2a} } +}; + +static mach64FIFOTable VTA3_DRAM_1M_5200[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4000, 0x02}, { 5200, 0x04}, { 9000, 0x06}, {24000, 0x0a} }, + { { 2300, 0x02}, { 3800, 0x04}, { 5200, 0x06}, { 7800, 0x0a}, + { 8500, 0x0c}, {24000, 0x0e} }, + { { 1500, 0x04}, { 3000, 0x06}, { 3500, 0x08}, { 3800, 0x0a}, + { 4000, 0x0c}, { 4500, 0x0e}, {24000, 0x2e} }, + { { 1500, 0x04}, { 3000, 0x06}, { 3500, 0x08}, { 3800, 0x0a}, + { 4000, 0x0c}, { 4500, 0x0e}, {24000, 0x2e} }, + { { 1500, 0x06}, { 2200, 0x0a}, { 3000, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } +}; + +static mach64FIFOTable VTA3_DRAM_2M_5200[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x02}, { 8200, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 3000, 0x02}, { 4600, 0x04}, { 6000, 0x06}, { 7600, 0x08}, + { 9000, 0x0a}, {10200, 0x0c}, {12200, 0x0e}, {24000, 0x0e} }, + { { 1500, 0x02}, { 2300, 0x04}, { 3000, 0x06}, { 3800, 0x08}, + { 4600, 0x0a}, { 5200, 0x0c}, { 7400, 0x28}, {24000, 0x0e} }, + { { 1500, 0x02}, { 2300, 0x04}, { 3000, 0x06}, { 3800, 0x08}, + { 4600, 0x0a}, { 5200, 0x0c}, { 7400, 0x28}, {24000, 0x0e} }, + { { 1500, 0x06}, { 2300, 0x08}, { 3000, 0x0a}, { 3300, 0x0c}, + { 3800, 0x0c}, { 4300, 0x0c}, { 4600, 0x0e}, {24000, 0x2c} }, + { { 1500, 0x06}, { 2300, 0x0a}, { 3400, 0x0c}, {24000, 0x2c} } +}; + +static mach64FIFOTable VTA3_DRAM_1M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x04}, { 7900, 0x06}, {24000, 0x0a} }, + { { 3800, 0x04}, { 5400, 0x06}, { 5800, 0x08}, { 7800, 0x0a}, + { 8500, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3400, 0x08}, { 3800, 0x0a}, + { 4400, 0x0c}, { 5000, 0x0e}, {24000, 0x2c} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3400, 0x08}, { 3800, 0x0a}, + { 4400, 0x0c}, { 5000, 0x0e}, {24000, 0x2c} }, + { { 2000, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA3_DRAM_2M_5600[MAX_CDEPTH][MAX_DOTCLOCKS]= +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 4600, 0x04}, { 5600, 0x06}, { 6600, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11200, 0x0c}, {14000, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 5800, 0x0c}, { 7000, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5200, 0x0a}, + { 5800, 0x0c}, { 7000, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5200, 0x0a}, + { 5800, 0x0c}, { 7000, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x0a}, { 3500, 0x0c}, { 3800, 0x0c}, { 4200, 0x0e}, + {24000, 0x2c} } +}; + +static mach64FIFOTable VTA4_SDRAM_1M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 3600, 0x04}, { 4400, 0x06}, { 5500, 0x06}, { 6800, 0x06}, + { 8100, 0x08}, { 9000, 0x08}, {10500, 0x0a}, {11500, 0x0c}, + {12600, 0x0c}, {24000, 0x0c} }, /* 8bpp */ + { { 2200, 0x06}, { 2600, 0x06}, { 3000, 0x06}, { 3400, 0x06}, + { 3700, 0x08}, { 3800, 0x08}, { 4400, 0x0a}, { 4900, 0x0c}, + { 5100, 0x0c}, { 5800, 0x0c}, { 6800, 0x0e}, {24000, 0x0e} }, /* 15bpp*/ + { { 2200, 0x06}, { 2600, 0x06}, { 3000, 0x06}, { 3400, 0x06}, + { 3700, 0x08}, { 3800, 0x08}, { 4400, 0x0a}, { 4900, 0x0c}, + { 5100, 0x0c}, { 5800, 0x0c}, { 6800, 0x0e}, {24000, 0x0e} }, /* 16bpp*/ + { { 2200, 0x08}, { 2600, 0x08}, { 3300, 0x0a}, { 3600, 0x0c}, + { 4000, 0x0e}, { 4500, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, /* 24bpp */ + { {24000, 0x08} } /* 32bpp */ +}; + +static mach64FIFOTable VTA4_SDRAM_2M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 3700, 0x04}, { 4000, 0x04}, { 5700, 0x06}, { 7900, 0x08}, + { 8100, 0x08}, { 9400, 0x08}, {11200, 0x0c}, {13200, 0x0e}, + {13600, 0x0e}, {24000, 0x0e} }, /* 8bpp */ + { { 2200, 0x06}, { 2600, 0x06}, { 3700, 0x08}, { 4200, 0x08}, + { 4600, 0x0a}, { 5000, 0x0c}, { 5700, 0x0c}, { 6400, 0x0c}, + { 6800, 0x0e}, { 7900, 0x0e}, { 8100, 0x0e}, {10000, 0x0e}, + {11000, 0x0e}, {24000, 0x0e} }, /* 15bpp */ + { { 2200, 0x06}, { 2600, 0x06}, { 3700, 0x08}, { 4200, 0x08}, + { 4600, 0x0a}, { 5000, 0x0c}, { 5700, 0x0c}, { 6400, 0x0c}, + { 6800, 0x0e}, { 7900, 0x0e}, { 8100, 0x0e}, {10000, 0x0e}, + {11000, 0x0e}, {24000, 0x0e} }, /* 16bpp */ + { { 2200, 0x0a}, { 2600, 0x0a}, { 3800, 0x0c}, { 4000, 0x0c}, + { 4500, 0x28}, { 5000, 0x2c}, { 5100, 0x2c}, { 5700, 0x2c}, + { 7500, 0x2c}, {24000, 0x2c} }, /* 24bpp */ + { { 2200, 0x0a}, { 2600, 0x0c}, { 3000, 0x0c}, { 3300, 0x0e}, + { 3400, 0x0e}, { 3800, 0x0e}, { 4000, 0x0e}, { 5000, 0x0e}, + { 5700, 0x0e}, { 6800, 0x0e}, {24000, 0x0e} } /* 32bpp */ +}; + +static mach64FIFOTable VTA4_SDRAM_1M_6300_5[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x08} }, + { { 3800, 0x04}, { 4400, 0x06}, { 6600, 0x06}, { 9000, 0x08}, + {24000, 0x0a} }, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, { 6900, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, { 6900, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 2600, 0x0a}, { 3400, 0x0c}, { 4200, 0x0e}, + { 4600, 0x0e}, {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA4_SDRAM_2M_6300_5[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, + { { 3000, 0x04}, { 4000, 0x06}, { 6000, 0x08}, { 9400, 0x0a}, + {10000, 0x0c}, {11200, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3500, 0x08}, { 4400, 0x0a}, { 6400, 0x0e}, + { 6800, 0x0e}, { 8200, 0x0e}, {10100, 0x0e}, {11100, 0x0e}, + {13100, 0x0e}, {13600, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3500, 0x08}, { 4400, 0x0a}, { 6400, 0x0e}, + { 6800, 0x0e}, { 8200, 0x0e}, {10100, 0x0e}, {11100, 0x0e}, + {13100, 0x0e}, {13600, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x0a}, { 4200, 0x0c}, { 4500, 0x28}, { 5200, 0x2c}, + { 5700, 0x2c}, { 6600, 0x2c}, { 6800, 0x2c}, { 7600, 0x2c}, + { 8200, 0x2c}, {10100, 0x2c}, {11100, 0x2c}, {12200, 0x2c}, + {24000, 0x2c} }, + { { 2000, 0x0a}, { 3000, 0x0c}, { 3400, 0x0e}, { 4100, 0x2e}, + { 4600, 0x2e}, { 5200, 0x2e}, { 5700, 0x2e}, { 6600, 0x2e}, + { 7000, 0x2e}, { 7600, 0x2e}, { 7900, 0x2e}, { 8200, 0x2e}, + {24000, 0x2e} } +}; + +static mach64FIFOTable VTA4_SDRAM_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 3600, 0x04}, { 4400, 0x06}, { 5800, 0x06}, { 7500, 0x06}, + { 8200, 0x08}, {11000, 0x0a}, {24000,0x0a}}, /* 8bpp */ + { { 2600, 0x06}, { 3200, 0x06}, { 3600, 0x08}, { 4000, 0x0a}, + { 4500, 0x0c}, { 5800, 0x0c}, { 8000, 0x0e}, {24000, 0x0e} }, /* 15bpp */ + { { 2600, 0x06}, { 3200, 0x06}, { 3600, 0x08}, { 4000, 0x0a}, + { 4500, 0x0c}, { 5800, 0x0c}, { 8000, 0x0e}, {24000, 0x0e} }, /* 16bpp */ + { { 2000, 0x08}, { 2600, 0x08}, { 3200, 0x0a}, { 3700, 0x0c}, + { 4200, 0x0c}, { 4600, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, /* 24bpp */ + { {24000, 0x06} } /* 32bpp */ +}; + +static mach64FIFOTable VTA4_SDRAM_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 4000, 0x04}, { 5800, 0x06}, { 8200, 0x08}, {10000, 0x0a}, + {11200, 0x0c}, {12200, 0x0e}, {13500, 0x0e}, {24000, 0x0e} }, /* 8bpp */ + { { 2600, 0x06}, { 4000, 0x08}, { 5100, 0x0a}, { 5800, 0x0c}, + { 6800, 0x0e}, { 8100, 0x0e}, {10000, 0x0e}, { 1100, 0x0e}, + {12200, 0x0e}, {12600, 0x0e}, {13500, 0x0e}, {24000, 0x0e} }, /* 15bpp */ + { { 2600, 0x06}, { 4000, 0x08}, { 5100, 0x0a}, { 5800, 0x0c}, + { 6800, 0x0e}, { 8100, 0x0e}, {10000, 0x0e}, {1100, 0x0e}, + {12200, 0x0e}, {12600, 0x0e}, {13500, 0x0e}, {24000, 0x0e} }, /* 16bpp */ + { { 2600, 0x0a}, { 4000, 0x0c}, { 4500, 0x28}, { 5200, 0x2c}, + { 5700, 0x2c}, { 6600, 0x2c}, { 6800, 0x2c}, { 7600, 0x2c}, + { 8200, 0x2c}, {10100, 0x2c}, {11100, 0x2c}, {12600, 0x2c}, + {24000, 0x2c} }, /* 24bpp */ + { { 2600, 0x0a}, { 3600, 0x0e}, { 4000, 0x0e}, { 4500, 0x2e}, + { 5200, 0x2e}, { 5700, 0x2e}, { 6600, 0x2e}, { 6800, 0x2e}, + { 7600, 0x2e}, { 8200, 0x2e}, {24000, 0x2e} } /* 32bpp */ +}; + +static mach64FIFOTable VTA4_SDRAM_1M_6700[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, { 8000, 0x08}, + {24000, 0x08} }, + { { 3800, 0x04}, { 4400, 0x06}, { 7800, 0x06}, { 9000, 0x08}, + {24000, 0x0a}}, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0c} }, + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0c} }, + { { 2000, 0x06}, { 2600, 0x06}, { 3400, 0x0a}, { 4100, 0x0c}, + {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA4_SDRAM_2M_6700[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x04}, { 9400, 0x06}, {11200, 0x08}, {24000, 0x08} }, + { { 4400, 0x04}, { 6600, 0x06}, { 9400, 0x08}, {10000, 0x0a}, + {11200, 0x0c}, {14000, 0x0c}, {24000, 0x0c}}, + { { 3400, 0x06}, { 4200, 0x08}, { 5400, 0x0a}, { 6600, 0x0c}, + { 8000, 0x0e}, {24000, 0x0e} }, + { { 3400, 0x06}, { 4200, 0x08}, { 5400, 0x0a}, { 6600, 0x0c}, + { 8000, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3000, 0x08}, { 3300, 0x0a}, { 4200, 0x0c}, + { 4600, 0x0c}, {24000, 0x2c} }, + { { 3000, 0x0a}, { 3400, 0x0c}, { 3800, 0x0e}, { 5200, 0x0e} } +}; + +static mach64FIFOTable VTA4_EDO_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 4800, 0x06}, { 5400, 0x06}, + { 6800, 0x0a}, { 7700, 0x0a}, { 9000, 0x0a}, {11000, 0x0c}, + {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } +}; + +static mach64FIFOTable VTA4_EDO_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11100, 0x0c}, {13000, 0x0c}, {14000, 0x0c}, + {24000,0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4100, 0x0a}, + { 4500, 0x0c}, { 5200, 0x0e}, { 5700, 0x2a}, { 6800, 0x2a}, + {24000, 0x2a} }, + { { 3000, 0x0a}, { 3500, 0x0e}, { 4200, 0x0e}, { 4600, 0x2a}, + { 5200, 0x2a}, {24000, 0x2a} } +}; + +static mach64FIFOTable VTA4_EDO_1M_6700_6[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 5400, 0x06}, { 7700, 0x0a}, + { 9000, 0x0a}, {10500, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 4800, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 4800, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA4_EDO_2M_6700_6[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11300, 0x0c}, {14000, 0x0c}, {24000, 0x0e}}, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4200, 0x0a}, + { 4500, 0x0c}, { 5200, 0x0c}, {24000, 0x2c} }, + { { 2000, 0x0a}, { 3000, 0x0a}, { 3500, 0x0c}, { 4200, 0x0e}, + {24000, 0x2a} } +}; + +static mach64FIFOTable VTA4_EDO_1M_6700_7[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4200, 0x04}, { 6400, 0x06}, { 9000, 0x0a}, {24000, 0x0c} }, + { { 3800, 0x08}, { 6400, 0x0a}, { 7000, 0x0c}, { 9000, 0x0c}, + {24000, 0x0c} }, + { { 3800, 0x0a}, { 4800, 0x0c}, { 5600, 0x0e}, {24000, 0x0e} }, + { { 3800, 0x0a}, { 4800, 0x0c}, { 5600, 0x0e}, {24000, 0x0e} }, + { { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA4_EDO_2M_6700_7[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x02}, { 7000, 0x04}, {10200, 0x06}, {24000, 0x0a} }, + { { 5200, 0x06}, { 6400, 0x08}, { 7000, 0x0a}, { 7900, 0x0c}, + { 8200, 0x0c}, {10800, 0x0c}, {13000, 0x0c}, {24000, 0x0c} }, + { { 3000, 0x06}, { 3800, 0x08}, { 4200, 0x0a}, { 5200, 0x0a}, + { 6600, 0x0c}, { 7600, 0x0c}, { 8200, 0x0c}, {24000, 0x0e} }, + { { 3000, 0x06}, { 3800, 0x08}, { 4200, 0x0a}, { 5200, 0x0c}, + { 6600, 0x0c}, { 7600, 0x0c}, { 8200, 0x0c}, {24000, 0x0e} }, + { { 3000, 0x0a}, { 3400, 0x0a}, { 3600, 0x0a}, { 4400, 0x0c}, + { 5200, 0x0c} }, + { { 3400, 0x0c}, { 5200, 0x0c} } +}; + +static mach64FIFOTable VTA4_PSEUDO_1M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 4000, 0x06}, { 5400, 0x06}, + { 7700, 0x0a}, { 8000, 0x0a}, { 9000, 0x0a}, {10500, 0x0c}, + {12000, 0x0c}, {12400, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3700, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5200, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3700, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5200, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } }; + +static mach64FIFOTable VTA4_PSEUDO_2M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 2000, 0x04}, { 3800, 0x04}, { 4600, 0x04}, { 5600, 0x06}, + { 7000, 0x06}, { 9400, 0x08}, {10000, 0x0a}, {11300, 0x0c}, + {12700, 0x0c}, {14000, 0x0c}, {24000, 0x0e} }, /* 8bpp */ + { { 2200, 0x06}, { 3400, 0x06}, { 3700, 0x08}, { 4200, 0x0a}, + { 4500, 0x0a}, { 5500, 0x0a}, { 6600, 0x0c}, { 7000, 0x0c}, + { 7600, 0x0e}, { 7900, 0x0e}, { 9000, 0x0e}, {10500, 0x0e}, + {11500, 0x0e}, {24000, 0x0e} }, /* 15bpp */ + { { 2200, 0x06}, { 3400, 0x06}, { 3700, 0x08}, { 4200, 0x0a}, + { 4500, 0x0a}, { 5500, 0x0a}, { 6600, 0x0c}, { 7000, 0x0c}, + { 7600, 0x0e}, { 7900, 0x0e}, { 9000, 0x0e}, {10500, 0x0e}, + {11500, 0x0e}, {24000, 0x0e} }, /* 16bpp */ + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4200, 0x0a}, + { 4500, 0x0c}, { 5200, 0x28}, { 6000, 0x2a}, { 6600, 0x2a}, + { 7000, 0x2a}, { 7900, 0x2a}, {24000, 0x2a} }, /* 24bpp */ + { { 2000, 0x0a}, { 3000, 0x0a}, { 3500, 0x0e}, { 3700, 0x0e}, + { 4200, 0x0e}, { 4500, 0x2a}, { 5100, 0x2a}, { 5600, 0x2a}, + {24000, 0x2a} } /* 32bpp */ +}; + +static mach64FIFOTable VTA4_PSEUDO_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, + { { 3000, 0x04}, { 3800, 0x04}, { 4800, 0x06}, { 5400, 0x06}, + { 6800, 0x0a}, { 7700, 0x0a}, { 9000, 0x0a}, {11100, 0x0c}, + {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3300, 0x0a}, { 4400, 0x0a}, + { 4800, 0x0e}, { 5500, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x0a}, { 3000, 0x0a}, { 3400, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } +}; + +static mach64FIFOTable VTA4_PSEUDO_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11100, 0x0c}, {13000, 0x0c}, {14000, 0x0c}, + {24000, 0x0e} }, + { { 2200, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2200, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5100, 0x0a}, + { 5500, 0x0c}, { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, + { 7900, 0x0e}, {11100, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4100, 0x0a}, + { 4500, 0x0c}, { 5200, 0x0e}, { 5700, 0x2a}, { 6800, 0x2a}, + {24000, 0x2a} }, + { { 3000, 0x0a}, { 3500, 0x0e}, { 4200, 0x0e}, { 4600, 0x2a}, + { 5200, 0x2a}, {24000, 0x2a} } +}; + +static mach64FIFOTable VTA4_DRAM_1M_5200[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4000, 0x02}, { 5200, 0x04}, { 9000, 0x06}, {24000, 0x0a} }, + { { 2300, 0x02}, { 3800, 0x04}, { 5200, 0x06}, { 7800, 0x0a}, + { 8500, 0x0c}, {24000, 0x0e} }, + { { 1500, 0x04}, { 3000, 0x06}, { 3500, 0x08}, { 3800, 0x0a}, + { 4000, 0x0c}, { 4500, 0x0e}, {24000, 0x2e} }, + { { 1500, 0x04}, { 3000, 0x06}, { 3500, 0x08}, { 3800, 0x0a}, + { 4000, 0x0c}, { 4500, 0x0e}, {24000, 0x2e} }, + { { 1500, 0x06}, { 2200, 0x0a}, { 3000, 0x0c}, {24000, 0x0e} }, + { {24000, 0x0c} } +}; + +static mach64FIFOTable VTA4_DRAM_2M_5200[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x02}, { 8200, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 3000, 0x02}, { 4600, 0x04}, { 6000, 0x06}, { 7600, 0x08}, + { 9000, 0x0a}, {10200, 0x0c}, {12200, 0x0e}, {24000, 0x0e} }, + { { 1500, 0x02}, { 2300, 0x04}, { 3000, 0x06}, { 3800, 0x08}, + { 4600, 0x0a}, { 5200, 0x0c}, { 7400, 0x28}, {24000, 0x0e} }, + { { 1500, 0x02}, { 2300, 0x04}, { 3000, 0x06}, { 3800, 0x08}, + { 4600, 0x0a}, { 5200, 0x0c}, { 7400, 0x28}, {24000, 0x0e} }, + { { 1500, 0x06}, { 2300, 0x08}, { 3000, 0x0a}, { 3300, 0x0c}, + { 3800, 0x0c}, { 4300, 0x0c}, { 4600, 0x0e}, {24000, 0x2c} }, + { { 1500, 0x06}, { 2300, 0x0a}, { 3400, 0x0c}, {24000, 0x2c} } +}; + +static mach64FIFOTable VTA4_DRAM_1M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x04}, { 7900, 0x06}, {24000, 0x0a} }, + { { 3800, 0x04}, { 5400, 0x06}, { 5800, 0x08}, { 7800, 0x0a}, + { 8500, 0x0c}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3400, 0x08}, + { 4400, 0x0c}, { 5000, 0x0e}, {24000, 0x2c} }, + { { 2000, 0x06}, { 3000, 0x06}, { 3400, 0x08}, + { 4400, 0x0c}, { 5000, 0x0e}, {24000, 0x2c} }, + { { 2000, 0x0a}, { 3000, 0x0a}, {24000, 0x0e} }, + { {24000, 0x06} } +}; + +static mach64FIFOTable VTA4_DRAM_2M_5600[MAX_CDEPTH][MAX_DOTCLOCKS]= +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, + { { 3400, 0x04}, { 4600, 0x04}, { 6600, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11200, 0x0c}, {14000, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 5800, 0x0c}, { 7000, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5200, 0x0a}, + { 5800, 0x0c}, { 7000, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5200, 0x0a}, + { 5800, 0x0c}, { 7000, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, + { { 3000, 0x0a}, { 3500, 0x0c}, { 3800, 0x0c}, { 4200, 0x0e}, + {24000, 0x2c} } +}; + +/* This is the CT-D fifo table */ +/* The datum were taken from the ct$9d-*.drm files */ +/*-------------------------------------------------------------------*/ + +/* The following two tables are extracted from CT9D-46.DRM */ +static mach64FIFOTable CTD_DRAM_2M_4600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3900, 0x04}, { 4700, 0x05}, { 5500, 0x06}, { 6300, 0x07}, + { 7100, 0x08}, { 7900, 0x09}, { 8700, 0x0a}, { 9500, 0x0b}, + {10300, 0x0c}, {11100, 0x0d}, {11900, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 4bpp */ + { { 4000, 0x04}, { 4700, 0x05}, { 5700, 0x06}, { 7600, 0x07}, + { 8000, 0x08}, { 8200, 0x09}, {10100, 0x0b}, {11100, 0x0d}, + {12700, 0x0f}, {24000, 0x10} }, /* 8bpp */ + { { 3300, 0x06}, { 4100, 0x08}, { 4600, 0x09}, { 5200, 0x0b}, + { 6600, 0x0f}, { 7900, 0x10}, { 8200, 0x13}, {24000, 0x1f} }, /* 15bpp */ + { { 3300, 0x06}, { 4100, 0x08}, { 4600, 0x09}, { 5200, 0x0b}, + { 6600, 0x0f}, { 7900, 0x10}, { 8200, 0x13}, {24000, 0x1f} }, /* 16bpp */ + { { 2700, 0x09}, { 3300, 0x0b}, { 4300, 0x0e}, { 4600, 0x10}, + { 5200, 0x12}, { 5700, 0x15}, {24000, 0x1f} }, /* 24bpp */ + { { 2600, 0x0b}, { 3300, 0x0f}, { 4100, 0x13}, { 4600, 0x15}, + {24000, 0x1f} } /* 32bpp */ +}; + +static mach64FIFOTable CTD_DRAM_1M_4600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3100, 0x04}, { 3800, 0x05}, { 4400, 0x06}, { 5100, 0x07}, + { 5700, 0x08}, { 6300, 0x09}, { 7000, 0x0a}, { 7600, 0x0b}, + { 8300, 0x0c}, { 8900, 0x0d}, { 9500, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 4bpp */ + { { 4100, 0x04}, { 4600, 0x05}, { 5200, 0x06}, { 5700, 0x07}, + { 7600, 0x09}, { 7900, 0x0a}, { 8200, 0x0b}, {24000, 0x1f} }, /* 8bpp*/ + { { 2800, 0x08}, { 3300, 0x09}, { 4100, 0x0b}, { 4600, 0x0c}, + {24000, 0x1f} }, /* 15bpp */ + { { 2800, 0x08}, { 3300, 0x09}, { 4100, 0x0b}, { 4600, 0x0c}, + {24000, 0x1f} }, /* 15bpp */ + { { 2500, 0x0d}, { 2700, 0x0e}, { 3300, 0x1c}, {24000, 0x1f} }, /* 24bpp */ + { {24000, 0x1f} } /* 32bpp */ +}; + + +/* The following four tables are extracted from CT9D-51.DRM */ +/* The tables CTD_.._4900 are created to cater for the DRAM Memory */ +/* Clock that is less than 49MHz. */ +/* Also some alternation is needed (in the function) to cater for the */ +/* condition of 1M, DRAM Memory Clock between 50MHz and 49MHz with 15 */ +/* and 16bpp */ +static mach64FIFOTable CTD_DRAM_2M_5100[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x04}, { 4700, 0x05}, { 5700, 0x06}, { 6700, 0x07}, + { 7600, 0x08}, { 8600, 0x09}, { 9500, 0x0a}, {10500, 0x0b}, + {11500, 0x0c}, {12400, 0x0d}, {13400, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 4bpp */ + { { 3800, 0x04}, { 4700, 0x05}, { 5700, 0x06}, { 6700, 0x07}, + { 7600, 0x08}, { 8600, 0x09}, { 9500, 0x0a}, {10500, 0x0b}, + {11500, 0x0c}, {12400, 0x0d}, {13400, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 8bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 4700, 0x09}, { 5300, 0x0a}, { 5500, 0x0b}, { 6300, 0x0c}, + { 6600, 0x0d}, { 7400, 0x0e}, { 7900, 0x0f}, { 9000, 0x11}, + {24000, 0x1f} }, /* 15bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 4700, 0x09}, { 5300, 0x0a}, { 5500, 0x0b}, { 6300, 0x0c}, + { 6600, 0x0d}, { 7400, 0x0e}, { 7900, 0x0f}, { 9000, 0x11}, + {24000, 0x1f} }, /* 16bpp */ + { { 2500, 0x09}, { 2900, 0x0a}, { 3300, 0x0b}, { 3600, 0x0c}, + { 4000, 0x0d}, { 4400, 0x0e}, { 4700, 0x10}, { 5100, 0x11}, + { 6500, 0x15}, { 7000, 0x16}, {24000, 0x1f} }, /* 24bpp */ + { { 2500, 0x0b}, { 2800, 0x0c}, { 3000, 0x0d}, { 3200, 0x0e}, + { 4000, 0x12}, { 4600, 0x13}, { 5200, 0x16}, {24000, 0x1f} } /* 32bpp*/ +}; + +static mach64FIFOTable CTD_DRAM_1M_5100[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10000, 0x0d}, {10700, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 4bpp */ + { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10000, 0x0d}, {11000, 0x1d}, {24000, 0x1f} }, /* 8bpp */ + { { 2700, 0x07}, { 3100, 0x08}, { 3500, 0x09}, { 3900, 0x0a}, + { 4300, 0x0b}, { 4700, 0x0c}, { 5100, 0x0d}, { 5500, 0x0e}, + {14000, 0x0f}, {24000, 0x1f} }, /* 15bpp */ + { { 2700, 0x07}, { 3100, 0x08}, { 3500, 0x09}, { 3900, 0x0a}, + { 4300, 0x0b}, { 4700, 0x0c}, { 5100, 0x0d}, { 5500, 0x0e}, + {14000, 0x0f}, {24000, 0x1f} }, /* 16bpp */ + { { 2700, 0x0a}, { 3000, 0x0b}, { 3500, 0x0d}, { 3800, 0x0e}, + { 8000, 0x0f}, {24000, 0x1f} }, /* 24bpp */ + { {24000, 0x0f} } /* 32bpp */ +}; + +static mach64FIFOTable CTD_DRAM_2M_4900[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x04}, { 4700, 0x05}, { 5700, 0x06}, { 6700, 0x07}, + { 7600, 0x08}, { 8600, 0x09}, { 9500, 0x0a}, {10500, 0x0b}, + {11500, 0x0c}, {12400, 0x0d}, {13400, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 4bpp */ + { { 3800, 0x04}, { 4700, 0x05}, { 5700, 0x06}, { 6700, 0x07}, + { 7600, 0x08}, { 8600, 0x09}, { 9500, 0x0a}, {10500, 0x0b}, + {11500, 0x0c}, {14000, 0x0f}, {24000, 0x1f} }, /* 8bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 4700, 0x09}, { 5200, 0x0b}, { 5500, 0x0c}, { 6600, 0x0d}, + { 7900, 0x0f}, { 9000, 0x12}, {24000, 0x1f} }, /* 15bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 4700, 0x09}, { 5200, 0x0b}, { 5500, 0x0c}, { 6600, 0x0d}, + { 7900, 0x0f}, { 9000, 0x12}, {24000, 0x1f} }, /* 16bpp */ + { { 2500, 0x09}, { 2900, 0x0a}, { 3300, 0x0b}, { 3600, 0x0c}, + { 4000, 0x0d}, { 4400, 0x0e}, { 4700, 0x10}, { 5100, 0x11}, + { 6500, 0x15}, { 7000, 0x16}, {24000, 0x1f} }, /* 24bpp */ + { { 2500, 0x0b}, { 2800, 0x0c}, { 3000, 0x0d}, { 3200, 0x0e}, + { 4000, 0x12}, { 4600, 0x15}, {24000, 0x1f} } /* 32bpp */ +}; + +static mach64FIFOTable CTD_DRAM_1M_4900[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10000, 0x0d}, {10700, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 4bpp */ + { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10100, 0x13}, {24000, 0x1f} }, /* 8bpp */ + { { 2700, 0x07}, { 3100, 0x08}, { 3500, 0x09}, { 3900, 0x0a}, + { 4300, 0x0b}, { 4700, 0x0c}, { 5000, 0x12}, {24000, 0x1f} }, /* 15bpp */ + { { 2700, 0x07}, { 3100, 0x08}, { 3500, 0x09}, { 3900, 0x0a}, + { 4300, 0x0b}, { 4700, 0x0c}, { 5000, 0x12}, {24000, 0x1f} }, /* 16bpp */ + { { 2700, 0x0a}, { 3000, 0x0b}, { 3500, 0x0e}, {24000, 0x1f} }, /* 24bpp */ + { {24000, 0x0f} } /* 32bpp */ +}; + +/* Fifo Table extracted from the file CT9D-54.DRM */ +static mach64FIFOTable CTD_DRAM_2M_5400[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x04}, { 4700, 0x05}, { 5700, 0x06}, { 6700, 0x07}, + { 7600, 0x08}, { 8600, 0x09}, { 9500, 0x0a}, {10500, 0x0b}, + {11500, 0x0c}, {12400, 0x0d}, {13400, 0x0e}, {14000, 0x0e}, + {24000, 0x1f} }, /* 4bpp */ + { { 3800, 0x04}, { 4700, 0x05}, { 5700, 0x06}, { 6700, 0x07}, + { 7600, 0x08}, { 8600, 0x09}, { 9500, 0x0a}, {10500, 0x0b}, + {11500, 0x0c}, {12400, 0x0d}, {13400, 0x0e}, {14000, 0x0f}, + {24000, 0x1f} }, /* 8bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 4700, 0x09}, { 5300, 0x0a}, { 5800, 0x0b}, { 6300, 0x0c}, + { 6900, 0x0d}, { 7400, 0x0e}, {14000, 0x0f}, {24000, 0x1f} }, /* 15bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 4700, 0x09}, { 5300, 0x0a}, { 5800, 0x0b}, { 6300, 0x0c}, + { 6900, 0x0d}, { 7400, 0x0e}, {14000, 0x0f}, {24000, 0x1f} }, /* 16bpp */ + { { 2500, 0x08}, { 2900, 0x09}, { 3300, 0x0a}, { 3600, 0x0b}, + { 4000, 0x0c}, { 4400, 0x0d}, { 4700, 0x0e}, {14000, 0x1f}, + {24000, 0x1f} }, /* 24bpp */ + { { 2500, 0x0b}, { 2800, 0x0c}, { 3000, 0x0d}, { 3200, 0x0e}, + {14000, 0x0f}, {24000, 0x1f} } /* 32bpp */ +}; + +static mach64FIFOTable CTD_DRAM_1M_5400[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10000, 0x0d}, {10700, 0x0e}, {24000, 0x1f} }, /* 4bpp */ + { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10000, 0x0d}, {10700, 0x0e}, {24000, 0x1f} }, /* 8bpp */ + { { 2700, 0x07}, { 3100, 0x08}, { 3500, 0x09}, { 3900, 0x0a}, + { 4300, 0x0b}, { 4700, 0x0c}, { 5100, 0x0d}, { 5500, 0x0e}, + {24000, 0x1f} }, /* 15bpp */ + { { 2700, 0x07}, { 3100, 0x08}, { 3500, 0x09}, { 3900, 0x0a}, + { 4300, 0x0b}, { 4700, 0x0c}, { 5100, 0x0d}, { 5500, 0x0e}, + {24000, 0x1f} }, /* 16bpp */ + { { 2700, 0x0a}, { 3000, 0x0b}, { 3300, 0x0c}, { 3500, 0x0d}, + { 3800, 0x0e}, {24000, 0x0f} }, /* 24bpp */ + { {24000, 0x0f} } /* 32bpp */ +}; + +/* Fifo Table extracted from the file CT9D-56.DRM */ +static mach64FIFOTable CTD_DRAM_2M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4700, 0x04}, { 5700, 0x05}, { 6700, 0x06}, { 7600, 0x07}, + { 8600, 0x08}, { 9500, 0x09}, {10500, 0x0a}, {11500, 0x0b}, + {12400, 0x0c}, {13400, 0x0d}, {14000, 0x0e}, {24000, 0x1f} }, /* 4bpp */ + { { 4700, 0x04}, { 5700, 0x05}, { 6700, 0x06}, { 7600, 0x07}, + { 8600, 0x08}, { 9500, 0x09}, {10500, 0x0a}, {11500, 0x0b}, + {12400, 0x0c}, {13400, 0x0d}, {14000, 0x0e}, {24000, 0x1f} }, /* 8bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 5300, 0x0a}, { 5800, 0x0b}, { 6300, 0x0c}, { 6900, 0x0d}, + { 7400, 0x0e}, { 9000, 0x0f}, {24000, 0x1f} }, /* 15bpp */ + { { 2600, 0x05}, { 3100, 0x06}, { 3700, 0x07}, { 4200, 0x08}, + { 5300, 0x0a}, { 5800, 0x0b}, { 6300, 0x0c}, { 6900, 0x0d}, + { 7400, 0x0e}, { 9000, 0x0f}, {24000, 0x1f} }, /* 16bpp */ + { { 2500, 0x07}, { 2900, 0x08}, { 3300, 0x09}, { 3600, 0x0a}, + { 4000, 0x0b}, { 4400, 0x0c}, { 4700, 0x0d}, { 5100, 0x0e}, + { 6500, 0x13}, { 7000, 0x14}, {24000, 0x1f} }, /* 24bpp */ + { { 3800, 0x0e}, { 4200, 0x0f}, { 5200, 0x14}, {24000, 0x1f} } /* 32bpp */ +}; + +static mach64FIFOTable CTD_DRAM_1M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10000, 0x0d}, {10700, 0x0e}, {24000, 0x1f} }, /* 4bpp */ + { { 3500, 0x04}, { 4300, 0x05}, { 5000, 0x06}, { 5700, 0x07}, + { 6400, 0x08}, { 7100, 0x09}, { 7900, 0x0a}, { 8600, 0x0b}, + { 9300, 0x0c}, {10000, 0x0d}, {10700, 0x0e}, {24000, 0x0f} }, /* 8bpp */ + { { 2700, 0x06}, { 3100, 0x07}, { 3500, 0x08}, { 3900, 0x09}, + { 4300, 0x0a}, { 4700, 0x0b}, { 5100, 0x0c}, { 5500, 0x0d}, + { 5900, 0x0e}, {24000, 0x1f} }, /* 15bpp */ + { { 2700, 0x06}, { 3100, 0x07}, { 3500, 0x08}, { 3900, 0x09}, + { 4300, 0x0a}, { 4700, 0x0b}, { 5100, 0x0c}, { 5500, 0x0d}, + { 5900, 0x0e}, {24000, 0x1f} }, /* 16bpp */ + { { 2700, 0x09}, { 3000, 0x0a}, { 3300, 0x0b}, { 3500, 0x0c}, + { 3800, 0x0d}, { 4100, 0x0e}, {24000, 0x1f} }, /* 24bpp */ + { { 2500, 0x0b}, { 2700, 0x0c}, { 2900, 0x0d}, { 3100, 0x0e}, + {24000, 0x1f} } /* 32bpp */ +}; + +/* This is the GT-A2 fifo table */ +/* The datum were taken from the gt$9a-*.* files */ +/*-------------------------------------------------------------------*/ +/* The FIFO TABLE FOR SDRAM */ +/*-------------------------------------------------------------------*/ +/* The fifo table for GT SDRAM of 60MHz */ +/* data was extracted from gt$9a-60.sdr */ +/* table for 2M Ram */ +static mach64FIFOTable GTA2_SDRAM_2M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, /* 4 bpp */ + { { 4000, 0x04}, { 6000, 0x06}, { 9400, 0x08}, {11200, 0x0c}, + {24000, 0x0e} }, /* 8 bpp */ + { { 3000, 0x06}, { 4200, 0x08}, { 4600, 0x0a}, { 6400, 0x0c}, + {24000, 0x0e} }, /* 565 */ + { { 3000, 0x06}, { 4200, 0x08}, { 4600, 0x0a}, { 6400, 0x0c}, + {24000, 0x0e} }, /* 565 */ + { { 3000, 0x0a}, { 3800, 0x0c}, { 4200, 0x0c}, { 4500, 0x28}, + {24000, 0x2c} }, /* 24bpp */ + { { 2000, 0x0a}, { 3000, 0x0c}, { 3400, 0x0e}, {24000, 0x0e} } /* 32bpp */ +}; + +/* table for 1M Ram */ +static mach64FIFOTable GTA2_SDRAM_1M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, { 8000, 0x08}, + {24000, 0x08} }, /* 4 bpp */ + { { 3800, 0x04}, { 4400, 0x06}, { 6800, 0x06}, { 9000, 0x08}, + {10500, 0x0a}, {24000, 0x0c} }, /* 8 bpp */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0e} }, /* 565 */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0e} }, /* 565 */ + { { 2000, 0x08}, { 2600, 0x08}, { 3300, 0x0a}, { 3700, 0x0c}, + { 4100, 0x0e}, {24000, 0x0e} }, /* 24bpp */ + { {24000, 0x06} } /* 32bpp */ +}; + +/* The fifo table for GT SDRAM of 63MHz */ +/* data was extracted from gt$9a-63.sdr */ +/* table for 2M Ram */ +static mach64FIFOTable GTA2_SDRAM_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4400, 0x04}, { 9400, 0x06}, {24000, 0x08} }, /* 4 bpp */ + { { 3800, 0x04}, { 6000, 0x06}, { 7600, 0x08}, { 9800, 0x0a}, + {11200, 0x0c}, {24000, 0x0e} }, /* 8 bpp */ + { { 3000, 0x06}, { 3800, 0x08}, { 5400, 0x0a}, { 6400, 0x0c}, + {24000, 0x0e} }, /* 565 */ + { { 3000, 0x06}, { 3800, 0x08}, { 5400, 0x0a}, { 6400, 0x0c}, + {24000, 0x0e} }, /* 565 */ + { { 3000, 0x0a}, { 3800, 0x0c}, { 4200, 0x0c}, { 4500, 0x2a}, + {24000, 0x2c} }, /* 24bpp */ + { { 2200, 0x0a}, { 3000, 0x0c}, { 3400, 0x0e}, {24000, 0x2e} } /* 32bpp */ +}; + +/* table for 1M Ram */ +static mach64FIFOTable GTA2_SDRAM_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, { 8000, 0x08}, + {24000, 0x08} }, /* 4 bpp */ + { { 3800, 0x04}, { 4400, 0x06}, { 6600, 0x06}, { 9000, 0x08}, + {24000, 0x0a} }, /* 8 bpp */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0e} }, /* 555 */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0e} }, /* 565 */ + { { 2600, 0x0a}, { 3400, 0x0c}, { 4200, 0x0c}, {24000, 0x0e} }, /*24bpp*/ + { {24000, 0x08} } /* 32bpp */ +}; + +/* The fifo table for GT SDRAM of 67MHz */ +/* data was extracted from gt$9a-67.sdr */ +/* table for 2M Ram */ +static mach64FIFOTable GTA2_SDRAM_2M_6700[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x04}, { 9400, 0x06}, {11200, 0x08}, {24000, 0x08} }, /* 4bpp */ + { { 4400, 0x04}, { 6600, 0x06}, { 9400, 0x08}, {10000, 0x0a}, + {11200, 0x0c}, {14000, 0x0c}, {24000, 0x0c} }, /* 8 bpp */ + { { 3400, 0x06}, { 4200, 0x08}, { 5400, 0x0a}, { 6600, 0x0c}, + { 8000, 0x0e}, {24000, 0x0e} }, /* 555 */ + { { 3400, 0x06}, { 4200, 0x08}, { 5400, 0x0a}, { 6600, 0x0c}, + { 8000, 0x0e}, {24000, 0x0e} }, /* 565 */ + { { 2000, 0x08}, { 3000, 0x08}, { 3300, 0x0a}, { 4200, 0x0c}, + { 4600, 0x0c}, {24000, 0x2c} }, /* 24bpp */ + { { 3000, 0x0a}, { 3400, 0x0c}, { 3800, 0x0e}, { 5200, 0x0e} } /* 32bpp */ +}; + +/* table for 1M Ram */ +static mach64FIFOTable GTA2_SDRAM_1M_6700[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, { 8000, 0x08}, + {24000, 0x08} }, /* 4 bpp */ + { { 3800, 0x04}, { 4400, 0x06}, { 7800, 0x06}, { 9000, 0x08}, + {24000, 0x0a} }, /* 8 bpp */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0c} }, /* 555 */ + { { 3000, 0x06}, { 3400, 0x06}, { 3800, 0x08}, { 4400, 0x0a}, + { 5800, 0x0c}, {24000, 0x0c} }, /* 565 */ + { { 2000, 0x06}, { 2600, 0x06}, { 3400, 0x0a}, { 4100, 0x0c}, + {24000, 0x0e} }, /* 24bpp */ + { {24000, 0x06} } /* 32bpp */ +}; + +/*------------------------------------------------------------------*/ +/* The FIFO TABLE FOR DRAM */ +/*------------------------------------------------------------------*/ +/* The fifo table for GT DRAM of 56MHz */ +/* data was extracted from gt$9a-56.dr */ +/* table for 2M Ram */ +static mach64FIFOTable GTA2_DRAM_2M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 7600, 0x04}, {10100, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 4600, 0x04}, { 5500, 0x06}, { 5800, 0x06}, { 7600, 0x08}, + { 8200, 0x0a}, {10100, 0x0c}, {11100, 0x0e}, {12300, 0x0e}, + {24000, 0x0e} }, /* 8 bpp */ + { { 2000, 0x04}, { 2200, 0x04}, { 2600, 0x06}, { 3700, 0x08}, + { 4600, 0x0a}, { 5200, 0x0c}, { 5700, 0x0e}, { 6600, 0x0e}, + { 8000, 0x0e}, { 24000, 0x0e} }, /* 555 */ + { { 2000, 0x04}, { 2200, 0x04}, { 2600, 0x06}, { 3700, 0x08}, + { 4600, 0x0a}, { 5200, 0x0c}, { 5700, 0x0e}, { 6600, 0x0e}, + { 8000, 0x0e}, {24000, 0x0e} }, /* 565 */ + { { 2600, 0x0a}, { 3200, 0x0c}, { 3600, 0x0c}, { 4100, 0x0c}, + { 4600, 0x0c}, {24000, 0x2c} }, /* 24bpp */ + { { 1500, 0x06}, { 2200, 0x0a}, { 2600, 0x0c}, { 3300, 0x0c}, + { 3700, 0x0c}, {24000, 0x0e} } /* 32bpp */ +}; + +/* table for 1M Ram */ +static mach64FIFOTable GTA2_DRAM_1M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7900, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { { 3300, 0x04}, { 4600, 0x06}, { 5500, 0x08}, { 6800, 0x0a}, + { 7900, 0x0c}, { 8100, 0x0e}, {24000, 0x0e} }, /* 8 bpp */ + { { 2600, 0x08}, { 3300, 0x0a}, { 3700, 0x0c}, { 4600, 0x0e}, + {24000, 0x0e} }, /* 555 */ + { { 2600, 0x08}, { 3300, 0x0a}, { 3700, 0x0c}, { 4600, 0x0e}, + {24000, 0x0e} }, /* 565 */ + { { 2000, 0x0a}, { 2600, 0x0c}, {24000, 0x0e} }, /* 24bpp */ + { { 1500, 0x08}, {24000, 0x0c} } /* 32bpp */ +}; + +/*-----------------------------------------------------* + * The FIFO TABLE FOR EDO RAM * + *-----------------------------------------------------* + * The fifo table for GT EDO RAM of 63MHz * + * data was extracted from gt$9a-63.edo * + * table for 2M Ram */ +static mach64FIFOTable GTA2_EDO_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 7600, 0x04}, {10200, 0x06}, {24000, 0x0a} }, /* 4bpp*/ + { { 4100, 0x04}, { 5200, 0x06}, { 5600, 0x08}, { 7600, 0x08}, + { 9400, 0x0a}, {10000, 0x0c}, {11300, 0x0e}, {13000, 0x0e}, + {24000, 0x0e} }, /* 8 bpp */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3700, 0x08}, { 4600, 0x0a}, + { 5200, 0x0c}, { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 555 */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3700, 0x08}, { 4600, 0x0a}, + { 5200, 0x0c}, { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 565 */ + { { 2700, 0x0a}, { 3300, 0x0c}, { 3900, 0x0c}, { 4600, 0x0c}, + { 5200, 0x0e}, {24000, 0x0e} }, /*24bpp */ + { { 2200, 0x0a}, { 2700, 0x0c}, { 3300, 0x0c}, { 3700, 0x0e}, + {24000, 0x0e} } /* 32bpp */ +}; + +/*table for 1M Ram*/ +static mach64FIFOTable GTA2_EDO_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3300, 0x04}, { 3800, 0x06}, + { 4800, 0x08}, { 6800, 0x0a}, { 9000, 0x0c}, {24000, 0x0e} }, /* 8bpp */ + { { 2600, 0x08}, { 3300, 0x0a}, { 4100, 0x0c}, { 4600, 0x0e}, + { 5200, 0x0c}, {24000, 0x0c} }, /* 555 */ + { { 2600, 0x08}, { 3300, 0x0a}, { 4100, 0x0c}, { 4600, 0x0e}, + { 5200, 0x0c}, {24000, 0x0c} }, /* 565 */ + { { 2400, 0x0a}, { 3000, 0x0c}, {24000, 0x0c} }, /* 24bpp */ + { { 1500, 0x08}, {24000, 0x0c} } /* 32bpp */ +}; + +/* The fifo table for GT DRAM of 67MHz */ +/* data was extracted from gt$9a-67.edo */ +/* table for 2M Ram */ +static mach64FIFOTable GTA2_EDO_2M_6700_6[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, /* 4bpp */ + { { 4600, 0x04}, { 5600, 0x06}, { 7000, 0x06}, { 9400, 0x08}, + {10000, 0x0a}, {11300, 0x0c}, {14000, 0x0c}, {24000, 0x0e} }, /* 8 bpp*/ + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, {24000, 0x0e} }, /* 555 */ + { { 2000, 0x06}, { 3400, 0x06}, { 4200, 0x08}, { 5500, 0x0a}, + { 6600, 0x0c}, { 7000, 0x0c}, { 7600, 0x0e}, {24000, 0x0e} }, /* 565 */ + { { 2000, 0x08}, { 3400, 0x0a}, { 3800, 0x0a}, { 4200, 0x0a}, + { 4500, 0x0c}, { 5200, 0x0c}, {24000, 0x2c} }, /*24bpp*/ + { { 2000, 0x0a}, { 3000, 0x0a}, { 3500, 0x0c}, { 4200, 0x0e}, + {24000, 0x2a} } /* 32bpp */ +}; + +/*table for 1M Ram*/ +static mach64FIFOTable GTA2_EDO_1M_6700_6[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { {3800, 0x02}, {5200, 0x04}, {7600, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { {3000, 0x04}, {3800, 0x04}, {5400, 0x06}, {7700, 0x0a}, + {9000, 0x0a}, {10500, 0x0c}, {24000, 0x0e} }, /* 8 bpp */ + { {2000, 0x06}, {3000, 0x06}, {3800, 0x08}, {4400, 0x0a}, + {4800, 0x0c}, {24000, 0x0e} }, /* 555 */ + { {2000, 0x06}, {3000, 0x06}, {3800, 0x08}, {4400, 0x0a}, + {4800, 0x0c}, {24000, 0x0e} }, /* 565 */ + { {2000, 0x0a}, {3000, 0x0a}, {3400, 0x0c}, {24000, 0x0e} }, /*24bpp*/ + { {24000, 0x06} } /* 32bpp */ +}; + + +/* The fifo table for GT EDO RAM of 67MHz * + * data was extracted from gt$9a-67.ed7 * + * table for 2M Ram */ +static mach64FIFOTable GTA2_EDO_2M_6700_7[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x02}, { 7000, 0x04}, {10200, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { { 5200, 0x06}, { 6400, 0x08}, { 7000, 0x0a}, { 7900, 0x0c}, + { 8200, 0x0c}, {10800, 0x0c}, {13000, 0x0c}, {24000, 0x0c} }, /* 8bpp */ + { { 3000, 0x06}, { 3800, 0x08}, { 4200, 0x0a}, { 5200, 0x0a}, + { 6600, 0x0c}, { 7600, 0x0c}, { 8200, 0x0c}, {24000, 0x0e} }, /* 555 */ + { { 3000, 0x06}, { 3800, 0x08}, { 4200, 0x0a}, { 5200, 0x0a}, + { 6600, 0x0c}, { 7600, 0x0c}, { 8200, 0x0c}, {24000, 0x0e} }, /* 565 */ + { { 3000, 0x0a}, { 3400, 0x0a}, { 3600, 0x0a}, { 4400, 0x0c}, + { 5200, 0x0c} }, /* 24bpp */ + { { 3400, 0x0c}, { 5200, 0x0c} } /* 32bpp */ +}; + +/*table for 1M Ram */ +static mach64FIFOTable GTA2_EDO_1M_6700_7[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4200, 0x04}, { 6400, 0x06}, { 9000, 0x0a}, {24000, 0x0c} }, /* 4bpp */ + { { 3800, 0x08}, { 6400, 0x0a}, { 7000, 0x0c}, { 9000, 0x0c}, + {24000, 0x0c} }, /* 8 bpp */ + { { 3800, 0x0a}, { 4800, 0x0c}, { 5600, 0x0e}, {24000, 0x0e} }, /* 555 */ + { { 3800, 0x0a}, { 4800, 0x0c}, { 5600, 0x0e}, {24000, 0x0e} }, /* 565 */ + { { 3400, 0x0c}, {24000, 0x0e} }, /*24bpp */ + { {24000, 0x06} } /* 32bpp */ +}; + +/*-----------------------------------------------------* + * The FIFO TABLE FOR PSEUDO EDO RAM * + *-----------------------------------------------------* + * The fifo table for GT PSEUDO EDO RAM of 56MHz * + * data was extracted from gt$9a-56.pdo */ + +/*table for 2M Ram*/ +static mach64FIFOTable GTA2_PSEUDO_2M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 7600, 0x04}, {10200, 0x06}, {24000, 0x0a} }, /* 4bpp*/ + { { 4100, 0x04}, { 5200, 0x06}, { 5600, 0x08}, { 7300, 0x08}, + { 9400, 0x0a}, {10000, 0x0c}, {11300, 0x0e}, {12600, 0x0e}, + {24000, 0x0e} }, /* 8 bpp */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3700, 0x08}, { 4600, 0x0a}, + { 5200, 0x0c}, { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 555 */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3700, 0x08}, { 4600, 0x0a}, + { 5200, 0x0c}, { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 565 */ + { { 2700, 0x0a}, { 3300, 0x0c}, { 3900, 0x0c}, { 4600, 0x0c}, + {24000, 0x0e} }, /*24bpp*/ + { { 2200, 0x0a}, { 2700, 0x0c}, { 3300, 0x0c}, { 3700, 0x0e}, + {24000, 0x0e} } /* 32bpp */ +}; + +/*Table for 1M Ram*/ +static mach64FIFOTable GTA2_PSEUDO_1M_5600[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3300, 0x04}, { 3800, 0x06}, + { 4800, 0x08}, { 6800, 0x0a}, {24000, 0x0e} }, /* 8 bpp */ + { { 2600, 0x08}, { 3300, 0x0a}, { 3900, 0x0c}, { 4400, 0x0e}, + { 4800, 0x0c}, {24000, 0x0c} }, /* 555 */ + { { 2600, 0x08}, { 3300, 0x0a}, { 3900, 0x0c}, { 4400, 0x0e}, + { 4800, 0x0c}, {24000, 0x0c} }, /* 565 */ + { { 2000, 0x0a}, { 3000, 0x0c}, {24000, 0x0e} }, /*24bpp*/ + { { 1500, 0x08}, {24000, 0x0e} } /* 32bpp */ +}; + + +/* The fifo table for GT PSEUDO EDO RAM of 58MHz * + * data was extracted from gt$9a-58.pdo */ + +/*table for 2M Ram */ +static mach64FIFOTable GTA2_PSEUDO_2M_5800[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 7600, 0x04}, {10200, 0x06}, {24000, 0x0a} }, /* 4bpp*/ + { { 4100, 0x04}, { 5200, 0x06}, { 5600, 0x08}, { 7500, 0x08}, + { 9400, 0x0a}, {10000, 0x0c}, {11300, 0x0e}, {12600, 0x0e}, + {24000, 0x0e} }, /* 8 bpp */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3700, 0x08}, { 4600, 0x0a}, + { 5200, 0x0c}, { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 555 */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3700, 0x08}, { 4600, 0x0a}, + { 5200, 0x0c}, { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 565 */ + { { 2700, 0x0a}, { 3300, 0x0c}, { 3900, 0x0c}, { 4600, 0x0c}, + {24000, 0x0e} }, /*24bpp*/ + { { 2200, 0x0a}, { 2700, 0x0c}, { 3300, 0x0c}, { 3700, 0x0e}, + {24000, 0x0e} } /* 32bpp */ +}; + +/*table for 1M Ram*/ +static mach64FIFOTable GTA2_PSEUDO_1M_5800[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { { 2400, 0x06}, { 2600, 0x0a}, { 3300, 0x04}, { 3800, 0x06}, + { 4800, 0x08}, { 6800, 0x0a}, { 9000, 0x0c}, {24000, 0x0e} }, /* 8 bpp */ + { { 2600, 0x08}, { 3300, 0x0a}, { 4100, 0x0c}, { 4600, 0x0e}, + { 5200, 0x0c}, {24000, 0x0c} }, /* 555 */ + { { 2600, 0x08}, { 3300, 0x0a}, { 4100, 0x0c}, { 4600, 0x0e}, + { 5200, 0x0c}, {24000, 0x0c} }, /* 565 */ + { { 2400, 0x0a}, { 3000, 0x0c}, {24000, 0x0c} }, /*24bpp */ + { { 1500, 0x08}, {24000, 0x0c} } /* 32bpp */ +}; + +/* The fifo table for GT PSEUDO EDO RAM of 60MHz * + * data was extracted from gt$9a-60.pdo */ + +/*table for 2M Ram*/ +static mach64FIFOTable GTA2_PSEUDO_2M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 9400, 0x04}, {11200, 0x06}, {24000, 0x08} }, /* 4bpp*/ + { { 3000, 0x04}, { 3300, 0x06}, { 4600, 0x04}, { 5600, 0x06}, + { 5800, 0x06}, { 7900, 0x08}, { 8200, 0x0a}, {11300, 0x0c}, + {13000, 0x0c}, {14000, 0x0c}, {24000, 0x0e} }, /* 8 bpp */ + { { 2400, 0x06}, { 2600, 0x08}, { 4100, 0x08}, { 4600, 0x0a}, + { 5500, 0x0c}, { 5700, 0x0e}, { 6600, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 555 */ + { { 2400, 0x06}, { 2600, 0x08}, { 4100, 0x08}, { 4600, 0x0a}, + { 5500, 0x0c}, { 5700, 0x0e}, { 6600, 0x0e}, { 7900, 0x0e}, + {24000, 0x0e} }, /* 565 */ + { { 2000, 0x08}, { 2600, 0x0a}, { 3300, 0x0c}, { 4000, 0x0c}, + { 4500, 0x26}, { 5200, 0x28}, {24000, 0x2a} }, /*24bpp*/ + { { 2000, 0x0a}, { 2200, 0x0c}, { 2600, 0x0c}, { 3300, 0x0e}, + { 4200, 0x0e}, {24000, 0x2a} } /* 32bpp */ +}; + +/*table for 1M Ram*/ +static mach64FIFOTable GTA2_PSEUDO_1M_6000[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x02}, { 5200, 0x04}, { 7600, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { { 2400, 0x04}, { 3000, 0x06}, { 3300, 0x06}, { 4600, 0x0a}, + { 5200, 0x08}, { 6800, 0x0a}, { 8200, 0x0c}, {10100, 0x0e}, + {24000, 0x0e} }, /* 8 bpp */ + { { 1500, 0x0a}, { 2000, 0x08}, { 2400, 0x0a}, { 2600, 0x08}, + { 3700, 0x0a}, { 4100, 0x0c}, { 4600, 0x0e}, { 5200, 0x0e}, + {24000, 0x0e} }, /* 555 */ + { { 1500, 0x0a}, { 2000, 0x08}, { 2400, 0x0a}, { 2600, 0x08}, + { 3700, 0x0a}, { 4100, 0x0c}, { 4600, 0x0e}, { 5200, 0x0e}, + {24000, 0x0e} }, /* 565 */ + { { 2000, 0x0a}, { 2200, 0x0c}, { 2600, 0x0c}, { 3300, 0x0c}, + {24000, 0x0e} }, /*24bpp*/ + { { 2000, 0x0c}, {24000, 0x0c} } /* 32bpp */ +}; + +/* The fifo table for GT PSEUDO EDO RAM of 60MHz * + * data was extracted from gt$9a-63.pdo */ + +/*table for 2M Ram*/ +static mach64FIFOTable GTA2_PSEUDO_2M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 4600, 0x02}, { 7600, 0x04}, {10200, 0x06}, {24000, 0x0a} }, /* 4bpp */ + { { 4600, 0x04}, { 5600, 0x06}, { 7600, 0x08}, { 9400, 0x0a}, + {10000, 0x0c}, {11300, 0x0e}, {13000, 0x0e}, {24000, 0x0e} }, /* 8 bpp*/ + { { 2400, 0x06}, { 3700, 0x08}, { 4600, 0x0a}, { 5200, 0x0c}, + { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, /* 555 */ + { { 2400, 0x06}, { 3700, 0x08}, { 4600, 0x0a}, { 5200, 0x0c}, + { 5800, 0x0e}, { 6900, 0x0e}, { 7900, 0x0e}, {24000, 0x0e} }, /* 565 */ + { { 2700, 0x0a}, { 3300, 0x0c}, { 3900, 0x0c}, { 4600, 0x0c}, + { 5200, 0x0e}, {24000, 0x0e} }, /*24bpp */ + { { 2200, 0x0a}, { 2700, 0x0c}, { 3300, 0x0c}, { 3700, 0x0e}, + {24000, 0x0e} } /* 32bpp */ +}; + +/*table for 1M Ram*/ +static mach64FIFOTable GTA2_PSEUDO_1M_6300[MAX_CDEPTH][MAX_DOTCLOCKS] = +{ { { 3800, 0x04}, { 5200, 0x04}, { 7600, 0x06}, { 8000, 0x0a}, + {24000, 0x0a} }, /* 4bpp*/ + { { 3800, 0x06}, { 4800, 0x08}, { 5800, 0x0a}, { 6800, 0x0a}, + { 9000, 0x0c}, {24000, 0x0e} }, /* 8 bpp */ + { { 3000, 0x08}, { 3400, 0x0a}, { 3800, 0x0e}, { 4400, 0x0e}, + { 5800, 0x0e}, {24000, 0x0e} }, /* 555 */ + { { 3000, 0x08}, { 3400, 0x0a}, { 3800, 0x0e}, { 4400, 0x0e}, + { 5800, 0x0e}, {24000, 0x0e} }, /* 565 */ + { { 2400, 0x0a}, { 3000, 0x0c}, { 3400, 0x0c}, {24000, 0x0c} }, /*24bpp*/ + { { 3400, 0x0c}, {24000, 0x0e} } /* 32bpp */ +}; + + +/* + * mach64FIFOdepthDefault -- + * Calculates the correct FIFO depth for the Mach64 depending on the + * color depth and clock selected. + */ +int mach64FIFOdepthDefault(cdepth, clock, width) + int cdepth; + int clock; + int width; +{ + int fifo_depth; + int index; + + fifo_depth = clock/100; + + switch (cdepth) { + case CRTC_PIX_WIDTH_15BPP: + case CRTC_PIX_WIDTH_16BPP: + fifo_depth <<= 1; + index = 1*6; + break; + case CRTC_PIX_WIDTH_24BPP: + fifo_depth = (fifo_depth << 1) + fifo_depth; + index = 2*6; + break; + case CRTC_PIX_WIDTH_32BPP: + fifo_depth <<= 2; + index = 3*6; + break; + default: + index = 0*6; + break; + } + + if (si->Mem_Size <= MEM_SIZE_1M) { + if (si->Mem_Size == MEM_SIZE_1M) index += 2; + fifo_depth /= 6; + } else { + index += 4; + fifo_depth /= 12; + } + + if (fifo_depth < defaultFIFOVals[index]) + fifo_depth = defaultFIFOVals[index]; + if (fifo_depth > defaultFIFOVals[index+1]) + fifo_depth = defaultFIFOVals[index+1]; + + return(fifo_depth); +} + + +/* + * mach64FIFOdepthVTA3 -- + * Calculates the correct FIFO depth for the Mach64 depending on the + * color depth and clock selected. + */ +int mach64FIFOdepthVTA3(cdepth, clock, width) + int cdepth; + int clock; + int width; +{ + int i, cdepth_index = (cdepth >> 8) - 1; + mach64FIFOTable *pFIFOTable; + + switch (si->Mem_Type) { + case SDRAM: + if (si->DRAMMemClk >= 6000 && si->DRAMMemClk < 6300) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_SDRAM_1M_6000[cdepth_index][0]; + else + pFIFOTable = &VTA3_SDRAM_2M_6000[cdepth_index][0]; + } else if (si->DRAMMemClk >= 6300 && si->DRAMMemClk < 6700) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_SDRAM_1M_6300[cdepth_index][0]; + else + pFIFOTable = &VTA3_SDRAM_2M_6300[cdepth_index][0]; + } else { /* 67MHz and up */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_SDRAM_1M_6700[cdepth_index][0]; + else + pFIFOTable = &VTA3_SDRAM_2M_6700[cdepth_index][0]; + } + break; + case EDO_DRAM: + if (si->DRAMMemClk >= 6300 && si->DRAMMemClk < 6700) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_EDO_1M_6300[cdepth_index][0]; + else + pFIFOTable = &VTA3_EDO_2M_6300[cdepth_index][0]; + } else { /* 67MHz and up */ + if (si->MemCycle <= 6) { /* 6 cycles */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_EDO_1M_6700_6[cdepth_index][0]; + else + pFIFOTable = &VTA3_EDO_2M_6700_6[cdepth_index][0]; + } else { /* 7 cycles */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_EDO_1M_6700_7[cdepth_index][0]; + else + pFIFOTable = &VTA3_EDO_2M_6700_7[cdepth_index][0]; + } + } + break; + case PSEUDO_EDO: + if (si->DRAMMemClk >= 6000 && si->DRAMMemClk < 6300) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_PSEUDO_1M_6000[cdepth_index][0]; + else + pFIFOTable = &VTA3_PSEUDO_2M_6000[cdepth_index][0]; + } else { /* 63MHz and up */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_PSEUDO_1M_6300[cdepth_index][0]; + else + pFIFOTable = &VTA3_PSEUDO_2M_6300[cdepth_index][0]; + } + break; + default: /* DRAM */ + if (si->DRAMMemClk >= 5200 && si->DRAMMemClk < 5600) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_DRAM_1M_5200[cdepth_index][0]; + else + pFIFOTable = &VTA3_DRAM_2M_5200[cdepth_index][0]; + } else { /* 63MHz and up */ + if (si->DRAMMemClk < 5650) { + switch (cdepth) { + case CRTC_PIX_WIDTH_15BPP: + case CRTC_PIX_WIDTH_16BPP: + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (VTA3_DRAM_2M_5600[cdepth_index][i].dotclock == 7000) + VTA3_DRAM_2M_5600[cdepth_index][i].dotclock = 7600; + break; + case CRTC_PIX_WIDTH_24BPP: + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (VTA3_DRAM_1M_5600[cdepth_index][i].dotclock == 3000) + VTA3_DRAM_1M_5600[cdepth_index][i].fifo_val = 0x0c; + break; + default: /* Table is fine as is */ + break; + } + } + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA3_DRAM_1M_5600[cdepth_index][0]; + else + pFIFOTable = &VTA3_DRAM_2M_5600[cdepth_index][0]; + } + break; + } + + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (clock <= (pFIFOTable+i)->dotclock) + return (pFIFOTable+i)->fifo_val; + + return 0; +} + + +/* + * mach64FIFOdepthVTA4 -- + * Calculates the correct FIFO depth for the Mach64 depending on the + * color depth and clock selected. + */ +int mach64FIFOdepthVTA4(cdepth, clock, width) + int cdepth; + int clock; + int width; +{ + int i, cdepth_index = (cdepth >> 8) - 1; + mach64FIFOTable *pFIFOTable; + + switch (si->Mem_Type) { + case SDRAM: + if (si->DRAMMemClk >= 6000 && si->DRAMMemClk < 6300) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_SDRAM_1M_6000[cdepth_index][0]; + else + pFIFOTable = &VTA4_SDRAM_2M_6000[cdepth_index][0]; + } else if (si->DRAMMemClk >= 6300 && si->DRAMMemClk < 6700) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_SDRAM_1M_6300[cdepth_index][0]; + else + pFIFOTable = &VTA4_SDRAM_2M_6300[cdepth_index][0]; + } else { /* 67MHz and up */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_SDRAM_1M_6700[cdepth_index][0]; + else + pFIFOTable = &VTA4_SDRAM_2M_6700[cdepth_index][0]; + } + break; + case EDO_DRAM: + if (si->DRAMMemClk >= 6300 && si->DRAMMemClk < 6700) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_EDO_1M_6300[cdepth_index][0]; + else + pFIFOTable = &VTA4_EDO_2M_6300[cdepth_index][0]; + } else { /* 67MHz and up */ + if (si->MemCycle <= 6) { /* 6 cycles */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_EDO_1M_6700_6[cdepth_index][0]; + else + pFIFOTable = &VTA4_EDO_2M_6700_6[cdepth_index][0]; + } else { /* 7 cycles */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_EDO_1M_6700_7[cdepth_index][0]; + else + pFIFOTable = &VTA4_EDO_2M_6700_7[cdepth_index][0]; + } + } + break; + case PSEUDO_EDO: + if (si->DRAMMemClk >= 6000 && si->DRAMMemClk < 6300) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_PSEUDO_1M_6000[cdepth_index][0]; + else + pFIFOTable = &VTA4_PSEUDO_2M_6000[cdepth_index][0]; + } else { /* 63MHz and up */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_PSEUDO_1M_6300[cdepth_index][0]; + else + pFIFOTable = &VTA4_PSEUDO_2M_6300[cdepth_index][0]; + } + break; + default: /* DRAM */ + if (si->DRAMMemClk >= 5200 && si->DRAMMemClk < 5600) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_DRAM_1M_5200[cdepth_index][0]; + else + pFIFOTable = &VTA4_DRAM_2M_5200[cdepth_index][0]; + } else { /* 63MHz and up */ + if (si->DRAMMemClk < 5650) { + switch (cdepth) { + case CRTC_PIX_WIDTH_15BPP: + case CRTC_PIX_WIDTH_16BPP: + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (VTA4_DRAM_2M_5600[cdepth_index][i].dotclock == 7000) + VTA4_DRAM_2M_5600[cdepth_index][i].dotclock = 7600; + break; + case CRTC_PIX_WIDTH_24BPP: + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (VTA4_DRAM_1M_5600[cdepth_index][i].dotclock == 3000) + VTA4_DRAM_1M_5600[cdepth_index][i].fifo_val = 0x0c; + break; + default: /* Table is fine as is */ + break; + } + } + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &VTA4_DRAM_1M_5600[cdepth_index][0]; + else + pFIFOTable = &VTA4_DRAM_2M_5600[cdepth_index][0]; + } + break; + } + + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (clock <= (pFIFOTable+i)->dotclock) + return (pFIFOTable+i)->fifo_val; + + return 0; +} + + +/* + * mach64FIFOdepthGT -- + * Calculates the correct FIFO depth for the Mach64 depending on the + * color depth and clock selected. + */ +int mach64FIFOdepthGT(cdepth, clock, width) + int cdepth; + int clock; + int width; +{ + int i, cdepth_index = (cdepth >> 8) - 1; + mach64FIFOTable *pFIFOTable; + + switch (si->Mem_Type) { + case SDRAM: + if (si->DRAMMemClk >= 6000 && si->DRAMMemClk < 6300) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_SDRAM_1M_6000[cdepth_index][0]; + else + pFIFOTable = >A2_SDRAM_2M_6000[cdepth_index][0]; + } else if (si->DRAMMemClk >= 6300 && si->DRAMMemClk < 6700) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_SDRAM_1M_6300[cdepth_index][0]; + else + pFIFOTable = >A2_SDRAM_2M_6300[cdepth_index][0]; + } else { /* 67MHz and up */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_SDRAM_1M_6700[cdepth_index][0]; + else + pFIFOTable = >A2_SDRAM_2M_6700[cdepth_index][0]; + } + break; + case EDO_DRAM: + if (si->DRAMMemClk >= 6300 && si->DRAMMemClk < 6700) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_EDO_1M_6300[cdepth_index][0]; + else + pFIFOTable = >A2_EDO_2M_6300[cdepth_index][0]; + } else { /* 67MHz and up */ + if (si->MemCycle <= 6) { /* 6 cycles */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_EDO_1M_6700_6[cdepth_index][0]; + else + pFIFOTable = >A2_EDO_2M_6700_6[cdepth_index][0]; + } else { /* 7 cycles */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_EDO_1M_6700_7[cdepth_index][0]; + else + pFIFOTable = >A2_EDO_2M_6700_7[cdepth_index][0]; + } + } + break; + case PSEUDO_EDO: + if (si->DRAMMemClk >= 5600 && si->DRAMMemClk < 5800) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_PSEUDO_1M_5600[cdepth_index][0]; + else + pFIFOTable = >A2_PSEUDO_2M_5600[cdepth_index][0]; + } else if (si->DRAMMemClk >= 5800 && si->DRAMMemClk < 6000) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_PSEUDO_1M_5800[cdepth_index][0]; + else + pFIFOTable = >A2_PSEUDO_2M_5800[cdepth_index][0]; + } else if (si->DRAMMemClk >= 6000 && si->DRAMMemClk < 6300) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_PSEUDO_1M_6000[cdepth_index][0]; + else + pFIFOTable = >A2_PSEUDO_2M_6000[cdepth_index][0]; + } else { /* 63MHz and up */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_PSEUDO_1M_6300[cdepth_index][0]; + else + pFIFOTable = >A2_PSEUDO_2M_6300[cdepth_index][0]; + } + break; + default: /* DRAM */ + /* Default to 56MHz */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = >A2_DRAM_1M_5600[cdepth_index][0]; + else + pFIFOTable = >A2_DRAM_2M_5600[cdepth_index][0]; + break; + } + + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (clock <= (pFIFOTable+i)->dotclock) + return (pFIFOTable+i)->fifo_val; + + return 0; +} + + +/* + * mach64FIFOdepthCT -- + * Calculates the correct FIFO depth for the Mach64 depending on the + * color depth and clock selected. + */ +int mach64FIFOdepthCT(cdepth, clock, width) + int cdepth; + int clock; + int width; +{ + int fifo_depth; + int index; + + fifo_depth = clock/100; + + switch (cdepth) { + case CRTC_PIX_WIDTH_15BPP: + case CRTC_PIX_WIDTH_16BPP: + fifo_depth <<= 1; + index = 1*6; + break; + case CRTC_PIX_WIDTH_24BPP: + fifo_depth = (fifo_depth << 1) + fifo_depth; + index = 2*6; + break; + case CRTC_PIX_WIDTH_32BPP: + fifo_depth <<= 2; + index = 3*6; + break; + default: + index = 0*6; + break; + } + + if (si->Mem_Size <= MEM_SIZE_1M) { + if (si->Mem_Size == MEM_SIZE_1M) index += 2; + fifo_depth /= 6; + } else { + index += 4; + fifo_depth /= 10; + } + + if (width <= 640) + index += 0; + else if (width <= 800) + index += 1*6*4; + else if (width <= 1024) + index += 2*6*4; + else + index += 3*6*4; + + if (fifo_depth < CT_FIFOVals[index]) + fifo_depth = CT_FIFOVals[index]; + if (fifo_depth > CT_FIFOVals[index+1]) + fifo_depth = CT_FIFOVals[index+1]; + + return(fifo_depth); +} + + +/* + * mach64FIFOdepthCTD -- + * Calculates the correct FIFO depth for the Mach64 depending on the + * color depth and clock selected. + */ +int mach64FIFOdepthCTD(cdepth, clock, width) + int cdepth; + int clock; + int width; +{ + int i, cdepth_index = (cdepth >> 8) - 1; + mach64FIFOTable *pFIFOTable; + + if (si->DRAMMemClk >= 5600) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &CTD_DRAM_1M_5600[cdepth_index][0]; + else + pFIFOTable = &CTD_DRAM_2M_5600[cdepth_index][0]; + } else if (si->DRAMMemClk >= 5400) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &CTD_DRAM_1M_5400[cdepth_index][0]; + else + pFIFOTable = &CTD_DRAM_2M_5400[cdepth_index][0]; + } else if (si->DRAMMemClk > 4900) { + if (si->DRAMMemClk <= 5000 && si->Mem_Size <= MEM_SIZE_1M && + (cdepth == CRTC_PIX_WIDTH_15BPP || + cdepth == CRTC_PIX_WIDTH_16BPP)) { + for (i = 0; i < MAX_DOTCLOCKS; i++) { + if (CTD_DRAM_1M_5100[cdepth_index][i].dotclock == 5100) + CTD_DRAM_1M_5100[cdepth_index][i].dotclock = 5000; + if (CTD_DRAM_1M_5100[cdepth_index][i].dotclock == 5500 || + CTD_DRAM_1M_5100[cdepth_index][i].dotclock == 14000) { + CTD_DRAM_1M_5100[cdepth_index][i].dotclock = 5200; + CTD_DRAM_1M_5100[cdepth_index][i].fifo_val = 0x10; + } + } + } + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &CTD_DRAM_1M_5100[cdepth_index][0]; + else + pFIFOTable = &CTD_DRAM_2M_5100[cdepth_index][0]; + } else if (si->DRAMMemClk >= 4800) { + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &CTD_DRAM_1M_4900[cdepth_index][0]; + else + pFIFOTable = &CTD_DRAM_2M_4900[cdepth_index][0]; + } else { /* <= 48MHz */ + if (si->Mem_Size <= MEM_SIZE_1M) + pFIFOTable = &CTD_DRAM_1M_4600[cdepth_index][0]; + else + pFIFOTable = &CTD_DRAM_2M_4600[cdepth_index][0]; + } + + for (i = 0; i < MAX_DOTCLOCKS; i++) + if (clock <= (pFIFOTable+i)->dotclock) + return (pFIFOTable+i)->fifo_val; + + return 0; +} diff --git a/src/add-ons/accelerants/atimach64/Mach64fifo.h b/src/add-ons/accelerants/atimach64/Mach64fifo.h new file mode 100644 index 0000000000..707572cac3 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/Mach64fifo.h @@ -0,0 +1,72 @@ +/* $XConsortium: mach64fifo.h /main/1 1996/10/27 18:06:29 kaleb $ */ +/* + * Copyright 1996 by Kevin E. Martin, Chapel Hill, North Carolina. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Kevin + * E. Martin not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Kevin E. Martin makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * KEVIN E. MARTIN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/mach64/mach64fifo.h,v 3.1 1996/12/27 06:55:52 dawes Exp $ */ + +extern int mach64FIFOdepthDefault( +#if NeedFunctionPrototypes + int cdepth, + int clock, + int width +#endif +); + +extern int mach64FIFOdepthVTA3( +#if NeedFunctionPrototypes + int cdepth, + int clock, + int width +#endif +); + +extern int mach64FIFOdepthVTA4( +#if NeedFunctionPrototypes + int cdepth, + int clock, + int width +#endif +); + +extern int mach64FIFOdepthGT( +#if NeedFunctionPrototypes + int cdepth, + int clock, + int width +#endif +); + +extern int mach64FIFOdepthCT( +#if NeedFunctionPrototypes + int cdepth, + int clock, + int width +#endif +); + +extern int mach64FIFOdepthCTD( +#if NeedFunctionPrototypes + int cdepth, + int clock, + int width +#endif +); diff --git a/src/add-ons/accelerants/atimach64/ProposeDisplayMode.c b/src/add-ons/accelerants/atimach64/ProposeDisplayMode.c new file mode 100644 index 0000000000..6ce76541e2 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/ProposeDisplayMode.c @@ -0,0 +1,399 @@ +#include + +#include "GlobalData.h" +#include "generic.h" + + +#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) +#define MODE_FLAGS (B_SCROLL | B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS) +#define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode)) + +static const display_mode mode_list[] = { +{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */ +{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */ +{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */ +{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */ +{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */ +{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_CMAP8, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */ +{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */ +{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */ +{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */ +{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(800X600X8.Z1) */ +{ { 56250, 800, 832, 896, 1048, 600, 601, 604, 631, T_POSITIVE_SYNC}, B_CMAP8, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */ +{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */ +{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(1024X768X8.Z1) */ +{ { 78750, 1024, 1040, 1136, 1312, 768, 769, 772, 800, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */ +{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_CMAP8, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */ +{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */ +{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */ +{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_CMAP8, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */ +{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */ +{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */ +{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_CMAP8, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */ +{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */ +{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */ +{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */ +{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */ +{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */ +{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_CMAP8, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */ +}; + + +/* create a mask of one "bits" bits wide */ +#define MASKFROMWIDTH(bits) ((1 << bits) - 1) + +/* + Validate a target display mode is both + a) a valid display mode for this device and + b) falls between the contraints imposed by "low" and "high" + + If the mode is not (or cannot) be made valid for this device, return B_ERROR. + If a valid mode can be constructed, but it does not fall within the limits, + return B_BAD_VALUE. + If the mode is both valid AND falls within the limits, return B_OK. +*/ +status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high) { + + const uint16 h_display_bits = MASKFROMWIDTH(8); + const uint16 h_sync_bits = MASKFROMWIDTH(5); + const uint16 h_total_bits = MASKFROMWIDTH(9); + const uint16 v_display_bits = MASKFROMWIDTH(11); + const uint16 v_sync_bits = MASKFROMWIDTH(5); + const uint16 v_total_bits = MASKFROMWIDTH(11); + + int i, color_depth; + + int mach64CDepths [] = { -1, 4, 8, 15, 16, 24, 32, -1 }; + + status_t + result = B_ERROR; + uint32 + row_bytes, + limit_clock; + double + target_refresh = ((double)target->timing.pixel_clock * 1000.0) / ((double)target->timing.h_total * (double)target->timing.v_total); + bool + want_same_width = target->timing.h_display == target->virtual_width, + want_same_height = target->timing.v_display == target->virtual_height; + + /* + NOTE: + Different devices provide different levels of control over the various CRTC values. + This code should be used as a *GUIDELINE ONLY*. The device you're controling may + have very different constraints, and the code below may be insufficient to insure + that a particular display_mode is valid for your device. You would do well to + spend quite a bit of time ensuring that you understand the limitations of your + device, as setting these values incorrectly can create a display_mode that could + turn your monitor into a useless slag of molten components, burn up your card, + lock up the PCI bus, cause partialy or multiply repeating display images, or + otherwise look just plain wierd. Honest. + */ + /* + NOTE: + This code doesn't explicitly support interlaced video modes. + */ + + /* validate horizontal timings */ + { + /* for most devices, horizontal parameters must be multiples of 8 */ + uint16 h_display = target->timing.h_display >> 3; + uint16 h_sync_start = target->timing.h_sync_start >> 3; + uint16 h_sync_end = target->timing.h_sync_end >> 3; + uint16 h_total = target->timing.h_total >> 3; + + /* ensure reasonable minium display and sequential order of parms */ + + if (h_display < (320 >> 3)) h_display = 320 >> 3; + if (h_display > (2048 >> 3)) h_display = 2048 >> 3; + if (h_sync_start < (h_display + 2)) h_sync_start = h_display + 2; + if (h_sync_end < (h_sync_start + 3)) h_sync_end = h_sync_start + 3; /*(0x001f >> 2);*/ + + if (h_total < (h_sync_end + 1)) h_total = h_sync_end + 1; + /* adjust for register limitations: */ + /* h_total is 9 bits */ + + if (h_total > h_total_bits) h_total = h_total_bits; + /* h_display is 8 bits - handled above */ + /* h_sync_start is 9 bits */ + /* h_sync_width is 5 bits */ + if ((h_sync_end - h_sync_start) > h_sync_bits) h_sync_end = h_sync_start + h_sync_bits; + + /* shift back to the full width values */ + + target->timing.h_display = h_display << 3; + target->timing.h_sync_start = h_sync_start << 3; + target->timing.h_sync_end = h_sync_end << 3; + target->timing.h_total = h_total << 3; + } + + /* did we fall out of one of the limits? */ + + if ( + (target->timing.h_display < low->timing.h_display) || + (target->timing.h_display > high->timing.h_display) || + (target->timing.h_sync_start < low->timing.h_sync_start) || + (target->timing.h_sync_start > high->timing.h_sync_start) || + (target->timing.h_sync_end < low->timing.h_sync_end) || + (target->timing.h_sync_end > high->timing.h_sync_end) || + (target->timing.h_total < low->timing.h_total) || + (target->timing.h_total > high->timing.h_total) + ) result = B_BAD_VALUE; + + + /* validate vertical timings */ + + { + uint16 v_display = target->timing.v_display; + uint16 v_sync_start = target->timing.v_sync_start; + uint16 v_sync_end = target->timing.v_sync_end; + uint16 v_total = target->timing.v_total; + + /* ensure reasonable minium display and sequential order of parms */ + /* v_display is 11 bits */ + /* v_total is 11 bits */ + /* v_sync_start is 11 bits */ + /* v_sync_width is 5 bits */ + + if (v_display < 200) v_display = 200; + if (v_display > (v_display_bits - 5)) v_display = (v_display_bits - 5); /* leave room for the sync pulse */ + if (v_sync_start < (v_display + 1)) v_sync_start = v_display + 1; + if (v_sync_end < v_sync_start) v_sync_end = v_sync_start + 3; + if (v_total < (v_sync_end + 1)) v_total = v_sync_end + 1; + /* adjust for register limitations */ + + if ((v_sync_end - v_sync_start) > v_sync_bits) v_sync_end = v_sync_start + v_sync_bits; + target->timing.v_display = v_display; + target->timing.v_sync_start = v_sync_start; + target->timing.v_sync_end = v_sync_end; + target->timing.v_total = v_total; + } + + /* did we fall out of one of the limits? */ + + if ( + (target->timing.v_display < low->timing.v_display) || + (target->timing.v_display > high->timing.v_display) || + (target->timing.v_sync_start < low->timing.v_sync_start) || + (target->timing.v_sync_start > high->timing.h_sync_start) || + (target->timing.v_sync_end < low->timing.v_sync_end) || + (target->timing.v_sync_end > high->timing.v_sync_end) || + (target->timing.v_total < low->timing.v_total) || + (target->timing.v_total > high->timing.v_total) + ) result = B_BAD_VALUE; + + /* adjust pixel clock for DAC limits and target refresh rate */ + /* + We're re-calcuating the pixel_clock here because we might have + changed the h/v totals above. If we didn't change anything + the calculation is wasted, but it's no big deal. + */ + target->timing.pixel_clock = target_refresh * ((double)target->timing.h_total) * ((double)target->timing.v_total) / 1000.0 + .5; + + /* + Select the maximum pixel clock based on the color space. Your + device may have other constraints. In this sample driver, we + calculated the maximum pixel clock for this device in the + initialization code. + This is also a convienient place to determine the number of bytes + per pixel for a later display pitch calculation. + */ + switch (target->space & 0x0fff) { + case B_CMAP8: + limit_clock = si->pix_clk_max8; + row_bytes = 1; + color_depth = 8; + break; + case B_RGB15: + case B_RGB16: + limit_clock = si->pix_clk_max16; + row_bytes = 2; + color_depth = 16; + break; + case B_RGB32: + limit_clock = si->pix_clk_max32; + row_bytes = 4; + color_depth = 32; + break; + default: + /* no amount of adjusting will fix not being able to support the pixel format */ + return B_ERROR; + } + /* make sure we don't generate more pixel bandwidth than the device can handle */ + + if (target->timing.pixel_clock > limit_clock) target->timing.pixel_clock = limit_clock; + /* we probably ought to check against too low of a pixel rate, but I'm lazy */ + + /* note if we fell outside the limits */ + if ( + (target->timing.pixel_clock < low->timing.pixel_clock) || + (target->timing.pixel_clock > high->timing.pixel_clock) + ) return B_ERROR; + + /* validate display vs. virtual */ + + if ((target->timing.h_display > target->virtual_width) || want_same_width) + target->virtual_width = target->timing.h_display; + if ((target->timing.v_display > target->virtual_height) || want_same_height) + target->virtual_height = target->timing.v_display; + if (target->virtual_width > 2048) + target->virtual_width = 2048; + + /* adjust virtual width for engine limitations */ + + target->virtual_width = (target->virtual_width + 7) & ~7; + if ( + (target->virtual_width < low->virtual_width) || + (target->virtual_width > high->virtual_width) + ) result = B_BAD_VALUE; + + /* calculate rowbytes after we've nailed the virtual width */ + + row_bytes *= target->virtual_width; + + /* memory requirement for frame buffer */ + + if ((row_bytes * target->virtual_height) > si->mem_size) + target->virtual_height = si->mem_size / row_bytes; + + if (target->virtual_height > 2048) + target->virtual_height = 2048; + + + if (target->virtual_height < target->timing.v_display){ + /* not enough frame buffer memory for the mode */ + return B_ERROR;} + else if ( + (target->virtual_height < low->virtual_height) || + (target->virtual_height > high->virtual_height) + ) result = B_BAD_VALUE; + + /* + Bit Flag Encoding + + The way the bit flags works is as follows: + + low high meaning + --- ---- ------- + 0 0 Feature must NOT be enabled + 0 1 Feature MAY be enabled, prefered enabled + 1 0 Feature MAY be enabled, prefered disabled + 1 1 Feature MUST be enabled + + */ + /* MORE WORK REQUIRED HERE. Current drivers mostly ignore the flags */ + + /* Look to see if there if the mode is doable */ + if (result != B_BAD_VALUE) + for(i = 0; si->Freq_Table[i].h_disp != 0; i++) { + + if ((si->Freq_Table[i].h_disp << 3 >= target->timing.h_display) && + (si->Freq_Table[i].dacmask >= si->DAC_SubType) && + (si->Freq_Table[i].max_dot_clock >= (target->timing.pixel_clock / 1000.0)) && + (mach64CDepths[si->Freq_Table[i].color_depth & 0x07] >= color_depth)){ + result = B_OK; + break; + } + } + + return result; + +} + +/* + Return the number of modes this device will return from GET_MODE_LIST(). +*/ +uint32 ACCELERANT_MODE_COUNT(void) { + /* return the number of 'built-in' display modes */ + return si->mode_count; +} + +/* + Copy the list of guaranteed supported video modes to the location + provided. +*/ +status_t GET_MODE_LIST(display_mode *dm) { + /* copy them to the buffer pointed at by *dm */ + memcpy(dm, atimach64_mode_list, si->mode_count * sizeof(display_mode)); + return B_OK; +} + + +status_t get_first_mode(display_mode *dm) { + /* copy first valid mode to the buffer pointed at by *dm */ + memcpy(dm, atimach64_mode_list, sizeof(display_mode)); + return B_OK; +} + + + +/* + Create a list of display_modes to pass back to the caller. +*/ +status_t create_mode_list(void) { + size_t max_size; + uint32 + i, j, + pix_clk_range; + const display_mode + *src; + display_mode + *dst, + low, + high; + + /* + We prefer frame buffers to have the same endianness as the host CPU, but it's + not required. You can even return both, although there isn't a way for the + current Screen preferences panel to allow the user to choose which one to use. + */ +#if defined(__INTEL__) + color_space spaces[4] = {B_CMAP8, B_RGB15_LITTLE, B_RGB16_LITTLE, B_RGB32_LITTLE}; +#else + color_space spaces[4] = {B_CMAP8, B_RGB15_BIG, B_RGB16_BIG, B_RGB32_BIG}; +#endif + + /* printf(" Mode count %ld \n", MODE_COUNT);*/ + + + + + /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */ + max_size = (((MODE_COUNT * 4) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1); + /* create an area to hold the info */ + si->mode_area = atimach64_mode_list_area = + create_area("ATIMACH64 accelerant mode info", (void **)&atimach64_mode_list, B_ANY_ADDRESS, max_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + if (atimach64_mode_list_area < B_OK) return atimach64_mode_list_area; + + /* walk through our predefined list and see which modes fit this device */ + src = mode_list; + dst = atimach64_mode_list; + si->mode_count = 0; + for (i = 0; i < MODE_COUNT; i++) { + /* set ranges for acceptable values */ + low = high = *src; + /* range is 6.25% of default clock: arbitrarily picked */ + + pix_clk_range = low.timing.pixel_clock >> 5; + low.timing.pixel_clock -= pix_clk_range; + high.timing.pixel_clock += pix_clk_range; + /* some cards need wider virtual widths for certain modes */ + high.virtual_width = 2048; + /* do it once for each depth we want to support */ + for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++) { + /* set target values */ + *dst = *src; + /* poke the specific space */ + dst->space = low.space = high.space = spaces[j]; + /* ask for a compatible mode */ + if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) { + /* count it, and move on to next mode */ + dst++; + si->mode_count++; + } + } + /* advance to next mode */ + src++; + } + + return B_OK; +} diff --git a/src/add-ons/accelerants/atimach64/SetDisplayMode.c b/src/add-ons/accelerants/atimach64/SetDisplayMode.c new file mode 100644 index 0000000000..e4b7647fc4 --- /dev/null +++ b/src/add-ons/accelerants/atimach64/SetDisplayMode.c @@ -0,0 +1,285 @@ +#include + +#include "GlobalData.h" +#include "generic.h" +#include "Mach64.h" +#include + + +/* + Enable/Disable interrupts. Just a wrapper around the + ioctl() to the kernel driver. +*/ +static void interrupt_enable(bool flag) { + status_t result; + atimach64_set_bool_state sbs; + + /* set the magic number so the driver knows we're for real */ + sbs.magic = ATIMACH64_PRIVATE_DATA_MAGIC; + sbs.do_it = flag; + /* contact driver and get a pointer to the registers and shared data */ + result = ioctl(fd, ATIMACH64_RUN_INTERRUPTS, &sbs, sizeof(sbs)); +} + +/* + Calculates the number of bits for a given color_space. + Usefull for mode setup routines, etc. +*/ +uint32 calcBitsPerPixel(uint32 cs) { + uint32 bpp = 0; + + switch (cs) { + case B_RGB32_BIG: + case B_RGBA32_BIG: + case B_RGB32_LITTLE: + case B_RGBA32_LITTLE: + bpp = 32; break; + case B_RGB24_BIG: + case B_RGB24_LITTLE: + bpp = 24; break; + case B_RGB16_BIG: + case B_RGB16_LITTLE: + bpp = 16; break; + case B_RGB15_BIG: + case B_RGBA15_BIG: + case B_RGB15_LITTLE: + case B_RGBA15_LITTLE: + bpp = 15; break; + case B_CMAP8: + bpp = 8; break; + } + return bpp; +} + +/* + The code to actually configure the display. Unfortunately, there's not much + that can be provided in the way of sample code. If you're lucky, you're writing + a driver for a device that has all (or at least most) of the bits for a particular + configuration value in the same register, rather than spread out over the standard + VGA registers + a zillion expansion bits. In any case, I've found that the way + to simplify this routine is to do all of the error checking in PROPOSE_DISPLAY_MODE(), + and just assume that the values I get here are acceptable. +*/ +static void do_set_display_mode(display_mode *dm) { + + mach64CRTCRegRec Regs; + + + CalcCRTCRegs(&Regs, dm); + + /* disable interrupts using the kernel driver */ + interrupt_enable(false); + + SetCRTCRegs(&Regs, dm); + + /* Initialize RAMDAC */ + InitRAMDAC(calcBitsPerPixel(dm->space), dm->flags); + + /* enable interrupts using the kernel driver */ + interrupt_enable(true); + +} + +/* + The exported mode setting routine. First validate the mode, then call our + private routine to hammer the registers. +*/ +status_t SET_DISPLAY_MODE(display_mode *mode_to_set) { + display_mode bounds, target; + + /* ask for the specific mode */ + target = bounds = *mode_to_set; + if (PROPOSE_DISPLAY_MODE(&target, &bounds, &bounds) == B_ERROR) + return B_ERROR; + + do_set_display_mode(&target); + + /* update shared info */ + target.h_display_start = 0; + target.v_display_start = 0; + si->dm = target; + + /* calculate bytes per row ans set it */ + si->fbc.bytes_per_row = ((calcBitsPerPixel(target.space) + 1) / 8) + *target.virtual_width; + + return B_OK; +} + +/* + Set which pixel of the virtual frame buffer will show up in the + top left corner of the display device. Used for page-flipping + games and virtual desktops. +*/ +status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) { + int byte_offset; + /* + Many devices have limitations on the granularity of the horizontal offset. + Make any checks for this here. A future revision of the driver API will + add a hook to return the granularity for a given display mode. + */ + /* most cards can handle multiples of 8 */ + if (h_display_start & 0x07) + return B_ERROR; + /* do not run past end of display */ + if ((si->dm.timing.h_display + h_display_start) > si->dm.virtual_width) + return B_ERROR; + if ((si->dm.timing.v_display + v_display_start) > si->dm.virtual_height) + return B_ERROR; + + /* everybody remember where we parked... */ + si->dm.h_display_start = h_display_start; + si->dm.v_display_start = v_display_start; + + /* Calculate offset remebering to include the cursor area */ + byte_offset = (si->fbc.frame_buffer - si->framebuffer) >> 3; + byte_offset += ((h_display_start + v_display_start*si->dm.virtual_width) * + (calcBitsPerPixel(si->dm.space) / 8)) >> 3; + + /* actually set the registers */ + if (~(si->dm.flags & B_HARDWARE_CURSOR)) + SHOW_CURSOR(false); + + outw(CRTC_OFF_PITCH, (inw(CRTC_OFF_PITCH) & 0xfff00000) | byte_offset); + + return B_OK; +} + +/* + Set the indexed color palette. +*/ +void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags) { + + /* + Some cards use the indexed color regisers in the DAC for gamma correction. + If this is true with your device (and it probably is), you need to protect + against setting these registers when not in an indexed mode. + */ + if (si->dm.space != B_CMAP8) return; + + /* + There isn't any need to keep a copy of the data being stored, as the app_server + will set the colors each time it switches to an 8bpp mode, or takes ownership + of an 8bpp mode after a GameKit app has used it. + */ + + /* + You're on your own from here. Chances are your code will look something like + what follows: + */ + /* + Due to the nature of the SAMPLE card, we need to do bytewise writes + to the dac regs. Stupid, but there you go. So, we do it like we're + supposed to. + */ + + WaitQueue(1); + + outb(DAC_REGS, first); + + while (count--) { + outb(DAC_REGS+1, *color_data++); + outb(DAC_REGS+1, *color_data++); + outb(DAC_REGS+1, *color_data++); + } +} + + +/* masks for DPMS control bits */ +enum { + H_SYNC_OFF = 0x01, + V_SYNC_OFF = 0x02, + DISPLAY_OFF = 0x04, + BITSMASK = H_SYNC_OFF | V_SYNC_OFF | DISPLAY_OFF +}; + +/* + Put the display into one of the Display Power Management modes. +*/ +status_t SET_DPMS_MODE(uint32 dpms_flags) { + uint32 LTemp; + + /* + The register containing the horizontal and vertical sync control bits + usually contains other control bits, so do a read-modify-write. + */ + /* read bits */ + LTemp = inw(CRTC_GEN_CNTL); + /* mask them */ + LTemp &= ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS); /* clear all disable bits (including display disable) */ + + /* now pick one of the DPMS configurations */ + switch(dpms_flags) { + case B_DPMS_ON: /* H: on, V: on */ + /* do nothing, bits already clear */ + /* usually, but it may be different for your device */ + break; + case B_DPMS_STAND_BY: /* H: off, V: on, display off */ + LTemp |= CRTC_HSYNC_DIS; + break; + case B_DPMS_SUSPEND: /* H: on, V: off, display off */ + LTemp |= CRTC_VSYNC_DIS; + break; + case B_DPMS_OFF: /* H: off, V: off, display off */ + LTemp |= CRTC_HSYNC_DIS | CRTC_VSYNC_DIS; + break; + default: + return B_ERROR; + } + /* write the bits */ + outw(CRTC_GEN_CNTL, LTemp); + + snooze(10000); + + /* + NOTE: if you're driving a device with a backlight (like a digital LCD), + you may want to turn off the backlight here when in a DPMS power saving mode. + */ + if (dpms_flags == B_DPMS_ON) + /* turn on the back light */ + ; + else + /* turn off the back light */ + ; + + return B_OK; +} + +/* + Report device DPMS capabilities. Most newer cards can do it all. + I've only seen one older card that can do a subset (ON and OFF). + Very early cards may not be able to do this at all. +*/ +uint32 DPMS_CAPABILITIES(void) { + return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF; +} + + +/* + Return the current DPMS mode. +*/ +uint32 DPMS_MODE(void) { + uint32 LTemp; + uint32 mode = B_DPMS_ON; + + /* read the control bits from the device */ + /* read the bits */ + LTemp = inw(CRTC_GEN_CNTL); + + /* what mode is set? */ + switch (LTemp & (CRTC_HSYNC_DIS | CRTC_VSYNC_DIS)) { + case 0: /* H: on, V: on */ + mode = B_DPMS_ON; + break; + case CRTC_HSYNC_DIS: /* H: off, V: on */ + mode = B_DPMS_STAND_BY; + break; + case CRTC_VSYNC_DIS: /* H: on, V: off */ + mode = B_DPMS_SUSPEND; + break; + case (CRTC_HSYNC_DIS | CRTC_VSYNC_DIS): /* H: off, V: off */ + mode = B_DPMS_OFF; + break; + } + return mode; +} diff --git a/src/add-ons/accelerants/atimach64/generic.h b/src/add-ons/accelerants/atimach64/generic.h new file mode 100644 index 0000000000..10d41e010e --- /dev/null +++ b/src/add-ons/accelerants/atimach64/generic.h @@ -0,0 +1,46 @@ +#if !defined(GENERIC_H) +#define GENERIC_H + +#include + +status_t INIT_ACCELERANT(int fd); +ssize_t ACCELERANT_CLONE_INFO_SIZE(void); +void GET_ACCELERANT_CLONE_INFO(void *data); +status_t CLONE_ACCELERANT(void *data); +void UNINIT_ACCELERANT(void); +status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi); +sem_id ACCELERANT_RETRACE_SEMAPHORE(void); + +uint32 ACCELERANT_MODE_COUNT(void); +status_t GET_MODE_LIST(display_mode *dm); +status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high); +status_t SET_DISPLAY_MODE(display_mode *mode_to_set); +status_t GET_DISPLAY_MODE(display_mode *current_mode); +status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *a_frame_buffer); +status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high); +status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start); +status_t GET_TIMING_CONSTRAINTS(display_timing_constraints *dtc); +void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags); + +uint32 DPMS_CAPABILITIES(void); +uint32 DPMS_MODE(void); +status_t SET_DPMS_MODE(uint32 dpms_flags); + +status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask); +void MOVE_CURSOR(uint16 x, uint16 y); +void SHOW_CURSOR(bool is_visible); + +uint32 ACCELERANT_ENGINE_COUNT(void); +status_t ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et); +status_t RELEASE_ENGINE(engine_token *et, sync_token *st); +void WAIT_ENGINE_IDLE(void); +status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st); +status_t SYNC_TO_TOKEN(sync_token *st); + +void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count); +void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count); +void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count); + +void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count); + +#endif diff --git a/src/add-ons/kernel/drivers/graphics/Jamfile b/src/add-ons/kernel/drivers/graphics/Jamfile index 33bc9ef516..3bda356523 100644 --- a/src/add-ons/kernel/drivers/graphics/Jamfile +++ b/src/add-ons/kernel/drivers/graphics/Jamfile @@ -6,3 +6,5 @@ SubInclude OBOS_TOP src add-ons kernel drivers graphics neomagic ; SubInclude OBOS_TOP src add-ons kernel drivers graphics nvidia ; SubInclude OBOS_TOP src add-ons kernel drivers graphics radeon ; SubInclude OBOS_TOP src add-ons kernel drivers graphics tdfx ; + +SubIncludeGPL OBOS_TOP src add-ons kernel drivers graphics atimach64 ; diff --git a/src/add-ons/kernel/drivers/graphics/atimach64/COPYING b/src/add-ons/kernel/drivers/graphics/atimach64/COPYING new file mode 100644 index 0000000000..a43ea2126f --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/atimach64/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/src/add-ons/kernel/drivers/graphics/atimach64/Jamfile b/src/add-ons/kernel/drivers/graphics/atimach64/Jamfile new file mode 100644 index 0000000000..961bc848f5 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/atimach64/Jamfile @@ -0,0 +1,19 @@ +SubDir OBOS_TOP src add-ons kernel drivers graphics atimach64 ; +SubDirCcFlags -DSEMAPHORE=1 ; + +UsePrivateHeaders graphics ; +UsePrivateHeaders [ FDirName graphics atimach64 ] ; + +R5KernelAddon atimach64.driver : kernel drivers bin : + driver.c + m64info.c +; + +# Link to kernel/drivers/dev/graphics +{ + local dir = [ FDirName $(OBOS_ADDON_DIR) kernel drivers dev graphics ] ; + local instDriver = atimach64.driver ; + MakeLocate $(instDriver) : $(dir) ; + RelSymLink $(instDriver) : atimach64.driver ; +} + diff --git a/src/add-ons/kernel/drivers/graphics/atimach64/driver.c b/src/add-ons/kernel/drivers/graphics/atimach64/driver.c new file mode 100644 index 0000000000..7178632ad5 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/atimach64/driver.c @@ -0,0 +1,976 @@ +/* + + Driver for ATIMach64VT + + Lots of rewriting to be able to work with other ATIMACH64 cards + + Rene MacKinney + + 6.May.1999 + + + Based on GraphicDriverKit for R4 alpha release + + Huge thanks to Trey for all the help + + +*/ + +/* standard kernel driver stuff */ +#include +#include +#include +#include + +/* this is for the standardized portion of the driver API */ +/* currently only one operation is defined: B_GET_ACCELERANT_SIGNATURE */ +#include + +/* this is for sprintf() */ +#include + +/* this is for string compares */ +#include + +/* The private interface between the accelerant and the kernel driver. */ +#include "DriverInterface.h" + +/* ATI Mach64 Definitions */ +#include "regmach64.h" +#include "ATIMach64.h" + +#if DEBUG > 0 +#define ddprintf(a) dprintf a +#else +#define ddprintf(a) +#endif + +#define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s)) +#define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v)) + +/* Given the fact that the VT is a motherboard integrated + card we only support one */ + +#define MAX_DEVICES 1 + +/* The vertical retrace semaphore is not implemented instead of erasing + all the code about it we simply don't compile it. Waiting for the + implementation */ + +#define SEMAPHORE 0 + + +/* Tell the kernel what revision of the driver API we support */ +int32 api_version = 2; + +/* these structures are private to the kernel driver */ +typedef struct device_info device_info; + +#if defined(POST_R4_0) +typedef struct { + timer te; /* timer entry for add_timer() */ + device_info *di; /* pointer to the owning device */ + bigtime_t when_target; /* when we're supposed to wake up */ +} timer_info; +#endif + +struct device_info { + uint32 is_open; /* a count of how many times the devices has been opened */ + area_id shared_area; /* the area shared between the driver and all of the accelerants */ + shared_info *si; /* a pointer to the shared area, for convenience */ + vuint32 *regs; /* kernel's pointer to memory mapped registers */ + int32 can_interrupt; /* when we're faking interrupts, let's us know if we should generate one */ +#if defined(POST_R4_0) + timer_info ti_a; /* a pool of two timer managment buffers */ + timer_info ti_b; + timer_info *current_timer; /* the timer buffer that's currently in use */ +#else + thread_id tid; +#endif +#if DEBUG > 0 + uint32 interrupt_count; /* if we're debugging, a count of how many times the interrupt handler has + been called for this device */ +#endif + pci_info pcii; /* a convenience copy of the pci info for this device */ + char name[B_OS_NAME_LENGTH]; /* where we keep the name of the device for publishing and comparing */ +}; + +typedef struct { +#if DEBUG > 0 + uint32 total_interrupts; /* total number of interrupts seen by our handler */ +#endif + uint32 count; /* number of devices actually found */ + benaphore kernel; /* for serializing opens/closes */ + char *device_names[MAX_DEVICES+1]; /* device name pointer storage */ + device_info di[MAX_DEVICES]; /* device specific stuff */ +} DeviceData; + +/* prototypes for our private functions */ +static status_t open_hook (const char* name, uint32 flags, void** cookie); +static status_t close_hook (void* dev); +static status_t free_hook (void* dev); +static status_t read_hook (void* dev, off_t pos, void* buf, size_t* len); +static status_t write_hook (void* dev, off_t pos, const void* buf, size_t* len); +static status_t control_hook (void* dev, uint32 msg, void *buf, size_t len); +static status_t map_device(device_info *di); +static void unmap_device(device_info *di); +static void probe_devices(void); +static int32 atimach64_interrupt(void *data); + +#if DEBUG > 0 +static int dump(int argc, char **argv); +#endif + +static DeviceData *pd; +static pci_module_info *pci_bus; +static device_hooks graphics_device_hooks = { + open_hook, + close_hook, + free_hook, + control_hook, + read_hook, + write_hook, + NULL, + NULL, + NULL, + NULL +}; + +static uint16 ati_device_list[] = { + PCI_MACH64_VT_ID, /* Mach64 VT device */ + 0 +}; + +static struct { + uint16 vendor; + uint16 *devices; +} SupportedDevices[] = { + {PCI_ATI_VENDOR_ID, ati_device_list}, + {0x0000, NULL} +}; + +/* + init_hardware() - Returns B_OK if one is + found, otherwise returns B_ERROR so the driver will be unloaded. +*/ +status_t +init_hardware(void) { + long pci_index = 0; + pci_info pcii; + bool found_one = FALSE; + + + /* choke if we can't find the PCI bus */ + if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK) + return B_ERROR; + + /* while there are more pci devices */ + while ((*pci_bus->get_nth_pci_info)(pci_index, &pcii) == B_NO_ERROR) { + int vendor = 0; + + ddprintf(("SKD init_hardware(): checking pci index %ld, device 0x%04x/0x%04x\n", pci_index, pcii.vendor_id, pcii.device_id)); + /* if we match a supported vendor */ + while (SupportedDevices[vendor].vendor) { + if (SupportedDevices[vendor].vendor == pcii.vendor_id) { + uint16 *devices = SupportedDevices[vendor].devices; + /* while there are more supported devices */ + while (*devices) { + /* if we match a supported device */ + if (*devices == pcii.device_id ) { + + ddprintf(("SKD: we support this device\n")); + found_one = TRUE; + goto done; + } + /* next supported device */ + devices++; + } + } + vendor++; + } + /* next pci_info struct, please */ + pci_index++; + } + ddprintf(("SKD: init_hardware - no supported devices\n")); + + done: + /* put away the module manager */ + put_module(B_PCI_MODULE_NAME); + return (found_one ? B_OK : B_ERROR); +} + +status_t +init_driver(void) { + + /* get a handle for the pci bus */ + if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK) + return B_ERROR; + + /* driver private data */ + pd = (DeviceData *)calloc(1, sizeof(DeviceData)); + if (!pd) { + put_module(B_PCI_MODULE_NAME); + return B_ERROR; + } + /* initialize the benaphore */ + INIT_BEN(pd->kernel); + /* find all of our supported devices */ + probe_devices(); +#if DEBUG > 0 + add_debugger_command("dump", dump, "dump ATIMach64 kernel driver persistant data"); +#endif + return B_OK; +} + +const char ** +publish_devices(void) { + /* return the list of supported devices */ + return (const char **)pd->device_names; +} + +device_hooks * +find_device(const char *name) { + int index = 0; + while (pd->device_names[index]) { + if (strcmp(name, pd->device_names[index]) == 0) + return &graphics_device_hooks; + index++; + } + return NULL; + +} + +void +uninit_driver(void) { + +#if DEBUG > 0 + remove_debugger_command("dump", dump); +#endif + + /* free the driver data */ + DELETE_BEN(pd->kernel); + free(pd); + pd = NULL; + + /* put the pci module away */ + put_module(B_PCI_MODULE_NAME); +} + +static status_t map_device(device_info *di) { + /* default: frame buffer in [0], control regs in [1] */ + /* int regs = 1; */ + int fb = 0; + char buffer[B_OS_NAME_LENGTH]; + shared_info *si = di->si; + uint32 tmpUlong; + pci_info *pcii = &(di->pcii); + uint32 rom_base; + + + /* enable memory mapped IO, disable VGA I/O */ + tmpUlong = get_pci(PCI_command, 4); + tmpUlong |= PCI_command_memory; + tmpUlong &= ~((uint32) PCI_command_io); + set_pci(PCI_command, 4, tmpUlong); + + /* enable ROM decoding */ + /* tmpUlong = get_pci(PCI_rom_base, 4); + tmpUlong |= PCI_rom_enable; + set_pci(PCI_rom_base, 4, tmpUlong); */ + + /* map the rom */ + /* If rom_base points to 0x00 try using standard ROM location for Mach64 */ + rom_base = (di->pcii.u.h0.rom_base == 0) ? 0x000c0000 : di->pcii.u.h0.rom_base; + sprintf(buffer, "%04X_%04X_%02X%02X%02X rom", + di->pcii.vendor_id, di->pcii.device_id, + di->pcii.bus, di->pcii.device, di->pcii.function); + si->rom_area = map_physical_memory( + buffer, + (void *)rom_base, + di->pcii.u.h0.rom_size, + B_ANY_KERNEL_ADDRESS, + B_READ_AREA, + (void **)&(si->rom)); + + /* return the error if there was some problem */ + if (si->rom_area < 0) { + delete_area(si->regs_area); + si->regs_area = -1; + return si->rom_area; + } + + sprintf(buffer, "%04X_%04X_%02X%02X%02X framebuffer", + di->pcii.vendor_id, di->pcii.device_id, + di->pcii.bus, di->pcii.device, di->pcii.function); + si->fb_area = map_physical_memory( + buffer, + (void *) di->pcii.u.h0.base_registers[fb], + di->pcii.u.h0.base_register_sizes[fb], +#if defined(__INTEL__) +#if defined(POST_R4_0) + B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, +#else + B_ANY_KERNEL_ADDRESS | B_MTR_WC, +#endif +#else + B_ANY_KERNEL_BLOCK_ADDRESS, +#endif + B_READ_AREA + B_WRITE_AREA, + &(si->framebuffer)); + +#if defined(__INTEL__) + if (si->fb_area < 0) { + /* try to map this time without write combining */ + /* + After R4.0 (Intel), map_physical_memory() will try B_ANY_KERNEL_ADDRESS if + a call with B_ANY_KERNEL_BLOCK_ADDRESS would fail. It always worked this way + under PPC. + */ + si->fb_area = map_physical_memory( + buffer, + (void *) di->pcii.u.h0.base_registers[fb], + di->pcii.u.h0.base_register_sizes[fb], +#if defined(POST_R4_0) + B_ANY_KERNEL_BLOCK_ADDRESS, +#else + B_ANY_KERNEL_ADDRESS, +#endif + B_READ_AREA + B_WRITE_AREA, + &(si->framebuffer)); + } +#endif + + /* if there was an error, delete our other areas */ + if (si->fb_area < 0) { + delete_area(si->regs_area); + si->regs_area = -1; + delete_area(si->rom_area); + si->rom_area = -1; + } + /* remember the DMA address of the frame buffer for BDirectWindow purposes */ + si->framebuffer_pci = (void *) di->pcii.u.h0.base_registers_pci[fb]; + + return si->fb_area; +} + +static void +unmap_device(device_info *di) { + shared_info *si = di->si; + uint32 tmpUlong; + pci_info *pcii = &(di->pcii); + + ddprintf(("unmap_device(%08lx) begins...\n", (uint32)di)); + ddprintf((" regs_area: %ld\n fb_area: %ld\n", si->regs_area, si->fb_area)); + /* disable memory mapped IO */ + tmpUlong = get_pci(PCI_command, 4); + tmpUlong &= 0xfffffffc; + set_pci(PCI_command, 4, tmpUlong); + /* disable ROM decoding */ + tmpUlong = get_pci(PCI_rom_base, 4); + tmpUlong &= 0xfffffffe; + set_pci(PCI_rom_base, 4, tmpUlong); + /* delete the areas */ + if (si->rom_area >= 0) delete_area(si->rom_area); + /* if (si->regs_area >= 0) delete_area(si->regs_area);*/ + if (si->fb_area >= 0) delete_area(si->fb_area); + si->rom_area = si->regs_area = si->fb_area = -1; + si->framebuffer = NULL; + di->regs = NULL; + si->rom = NULL; + ddprintf(("unmap_device() ends.\n")); +} + +static void +probe_devices(void) { + uint32 pci_index = 0; + uint32 count = 0; + device_info *di = pd->di; + + /* while there are more pci devices */ + while ((count < MAX_DEVICES) && ((*pci_bus->get_nth_pci_info)(pci_index, &(di->pcii)) == B_NO_ERROR)) { + int vendor = 0; + + /* if we match a supported vendor */ + while (SupportedDevices[vendor].vendor) { + if (SupportedDevices[vendor].vendor == di->pcii.vendor_id) { + uint16 *devices = SupportedDevices[vendor].devices; + /* while there are more supported devices */ + while (*devices) { + /* if we match a supported device */ + if (*devices == di->pcii.device_id ) { + /* publish the device name */ + sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X", + di->pcii.vendor_id, di->pcii.device_id, + di->pcii.bus, di->pcii.device, di->pcii.function); + ddprintf(("SKD: making /dev/%s\n", di->name)); + /* remember the name */ + pd->device_names[count] = di->name; + /* mark the driver as available for R/W open */ + di->is_open = 0; + /* mark areas as not yet created */ + di->shared_area = -1; + /* mark pointer to shared data as invalid */ + di->si = NULL; + /* inc pointer to device info */ + di++; + /* inc count */ + count++; + /* break out of these while loops */ + goto next_device; + } + /* next supported device */ + devices++; + } + } + vendor++; + } + next_device: + /* next pci_info struct, please */ + pci_index++; + } + /* propagate count */ + pd->count = count; + /* terminate list of device names with a null pointer */ + pd->device_names[pd->count] = NULL; + ddprintf(("SKD probe_devices: %ld supported devices\n", pd->count)); +} + +static uint32 +thread_interrupt_work(int32 *flags, vuint32 *regs, shared_info *si) { + uint32 handled = B_HANDLED_INTERRUPT; + /* release the vblank semaphore */ + if (si->vblank >= 0) { + int32 blocked; + if ((get_sem_count(si->vblank, &blocked) == B_OK) && (blocked < 0)) { + release_sem_etc(si->vblank, -blocked, B_DO_NOT_RESCHEDULE); + handled = B_INVOKE_SCHEDULER; + } + } + return handled; +} + +static int32 +atimach64_interrupt(void *data) +{ + int32 handled = B_UNHANDLED_INTERRUPT; + device_info *di = (device_info *)data; + shared_info *si = di->si; + int32 *flags = &(si->flags); + vuint32 *regs; + +#if DEBUG > 0 + pd->total_interrupts++; +#endif + + /* is someone already handling an interrupt for this device? */ + if (atomic_or(flags, SKD_HANDLER_INSTALLED) & SKD_HANDLER_INSTALLED) { +#if DEBUG > 0 + kprintf("SKD: Already in handler!\n"); +#endif + goto exit0; + } + /* get regs */ + regs = di->regs; + + /* read the interrrupt status register */ + + /* did this card cause an interrupt */ + if (0 /* replace this expression */) { + /* do our stuff */ + handled = thread_interrupt_work(flags, regs, si); +#if DEBUG > 0 + /* increment the counter for this device */ + di->interrupt_count++; +#endif + /* clear the interrupt status */ + } + + /* note that we're not in the handler any more */ + atomic_and(flags, ~SKD_HANDLER_INSTALLED); + + exit0: + return handled; +} + +#if SEMAPHORE +#if defined(POST_R4_0) +static int32 timer_interrupt_func(timer *te, uint32 pc) { + bigtime_t now = system_time(); + /* get the pointer to the device we're handling this time */ + device_info *di = ((timer_info *)te)->di; + shared_info *si = di->si; + int32 *flags = &(si->flags); + vuint32 *regs = di->regs; + uint32 vbl_status = 0 /* read vertical blank status */; + int32 result = B_HANDLED_INTERRUPT; + + /* are we suppoesed to handle interrupts still? */ + if (atomic_and(flags, -1) & SKD_HANDLER_INSTALLED) { + /* reschedule with same period by default */ + bigtime_t when = si->refresh_period; + timer *to; + + /* if interrupts are "enabled", do our thing */ + if (di->can_interrupt) { + /* insert code to sync to interrupts here */ + if (!vbl_status) { + when -= si->blank_period - 4; + } + /* do the things we do when we notice a vertical retrace */ + result = thread_interrupt_work(flags, regs, si); + + } + + /* pick the "other" timer */ + to = (timer *)&(di->ti_a); + if (to == te) to = (timer *)&(di->ti_b); + /* our guess as to when we should be back */ + ((timer_info *)to)->when_target = now + when; + /* reschedule the interrupt */ + add_timer(to, timer_interrupt_func, ((timer_info *)to)->when_target, B_ONE_SHOT_ABSOLUTE_TIMER); + /* remember the currently active timer */ + di->current_timer = (timer_info *)to; + } + + return result; +} +#else +static int32 +fake_interrupt_thread_func(void *_di) +{ + device_info *di; /* = (device_info *)_di; */ + shared_info *si; /* = di->si; */ + int32 *flags; /* = &(si->flags); */ + vuint32 *regs; /* = di->regs; */ + + bigtime_t last_sync; + bigtime_t this_sync; + bigtime_t diff_sync; + + uint32 counter = 1; + + ddprintf((" Device info points to %08x\n",(device_info *)_di)); + di = (device_info *)_di; + ddprintf((" Shared info points to %08x\n",di->si)); + si = di->si; + ddprintf((" Flags points to %08x\n",&(si->flags))); + flags = &(si->flags); + ddprintf((" Regs points to %08x\n",di->regs)); + regs = di->regs; + + /* a lie, but we have to start somewhen */ + + last_sync = system_time() - 8333; + + ddprintf(("fake_interrupt_thread_func begins\ndi: 0x%08lx\nsi: 0x%08lx\nflags: 0x%08lx\n", (uint32)di, (uint32)si, (uint32)flags)); + + /* loop until notified */ + + while(atomic_and(flags, -1) & SKD_HANDLER_INSTALLED) { + /* see if "interrupts" are enabled */ + + if((volatile int32)(di->can_interrupt)) { + /* poll the retrace flag until set */ + + /* YOUR CODE HERE */ + + /* get the system_time */ + this_sync = system_time(); + + /* do our stuff */ + thread_interrupt_work(flags, regs, si); + } else { + /* get the system_time */ + this_sync = system_time(); + } + + /* find out how long it took */ + diff_sync = this_sync - last_sync; + + /* back off a little so we're sure to catch the retrace */ + diff_sync -= diff_sync / 10; + + /* + impose some limits so we can recover from refresh rate changes + Supported refresh rates are 48 Hz - 120 Hz, so these limits should + be slightly wider. + */ + if(diff_sync < 8000) { + diff_sync = 8000; /* not less than 1/125th of sec */ + } + + if(diff_sync > 16666) { + diff_sync = 20000; /* not more than 1/40th of sec */ + } + + if((counter++ & 0x01ff) == 0) { + diff_sync >>= 2; /* periodically quarter the wait to resync */ + } + + /* update for next go-around */ + last_sync = this_sync; + + /* snooze until our next retrace */ + + snooze_until(this_sync + diff_sync, B_SYSTEM_TIMEBASE); + } + + ddprintf(("fake_interrupt_thread_func ends with flags = 0x%08lx\n", *flags)); + + /* gotta return something */ + + return B_OK; +} +#endif +#endif + +#if DEBUG > 0 +static int dump(int argc, char **argv) { + int i; + + kprintf("ATIMach64 Kernel Driver Persistant Data\n\nThere are %ld card(s)\n", pd->count); + kprintf("Driver wide benahpore: %ld/%ld\n", pd->kernel.ben, pd->kernel.sem); + + kprintf("Total seen interrupts: %ld\n", pd->total_interrupts); + for (i = 0; i < pd->count; i++) { + device_info *di = &(pd->di[i]); + uint16 device_id = di->pcii.device_id; + shared_info *si = di->si; + kprintf(" device_id: 0x%04x\n", device_id); + kprintf(" interrupt count: %ld\n", di->interrupt_count); + if (si) { + kprintf(" cursor: %d,%d\n", si->cursor.x, si->cursor.y); + kprintf(" flags:"); + if (si->flags & SKD_MOVE_CURSOR) kprintf(" SKD_MOVE_CURSOR"); + if (si->flags & SKD_PROGRAM_CLUT) kprintf(" SKD_PROGRAM_CLUT"); + if (si->flags & SKD_SET_START_ADDR) kprintf(" SKD_SET_START_ADDR"); + kprintf(" vblank semaphore id: %ld\n", si->vblank); + } + } + + + return 1; /* the magic number for success */ +} +#endif + +static status_t open_hook (const char* name, uint32 flags, void** cookie) { + int32 index = 0; + device_info *di; + shared_info *si; +#if SEMAPHORE + thread_id thid; + thread_info thinfo; +#endif + status_t result = B_OK; + vuint32 *regs; + char shared_name[B_OS_NAME_LENGTH]; + + ddprintf(("SKD open_hook(%s, %ld, 0x%08lx)\n", name, flags, (uint32)cookie)); + + /* find the device name in the list of devices */ + /* we're never passed a name we didn't publish */ + while (pd->device_names[index] && (strcmp(name, pd->device_names[index]) != 0)) index++; + + /* for convienience */ + di = &(pd->di[index]); + + /* make sure no one else has write access to the common data */ + AQUIRE_BEN(pd->kernel); + + /* if it's already open for writing */ + if (di->is_open) { + /* mark it open another time */ + goto mark_as_open; + } + /* create the shared area */ + sprintf(shared_name, "%04X_%04X_%02X%02X%02X shared", + di->pcii.vendor_id, di->pcii.device_id, + di->pcii.bus, di->pcii.device, di->pcii.function); + /* create this area with NO user-space read or write permissions, to prevent accidental dammage */ + di->shared_area = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 0); + if (di->shared_area < 0) { + /* return the error */ + result = di->shared_area; + goto done; + } + + /* save a few dereferences */ + si = di->si; + + /* save the vendor and device IDs */ + si->vendor_id = di->pcii.vendor_id; + si->device_id = di->pcii.device_id; + si->revision = di->pcii.revision; + + + /* map the device */ + result = map_device(di); + + if (result < 0) goto free_shared; + + /* Find registers in memory */ + /* This is the place for 2MB and 8MB boards */ + si->regs = (void *)((unsigned int)si->framebuffer + 0x7ffc00); + if ((unsigned int)si->device_id != (inw(CONFIG_CHIP_ID) & CFG_CHIP_TYPE)) { + /* Try place for 4MB */ + si->regs = (void *)((unsigned int)si->framebuffer + 0x3ffc00); + if (si->device_id != (inw(CONFIG_CHIP_ID) & CFG_CHIP_TYPE)) { + ddprintf(("Registers not found ! \n")); + goto free_shared; + } + } + + /* obtain all information related to the Mach64 */ + + result = GetATIInfo(si); + if (result < 0) goto free_shared; + + + /* create a semaphore for vertical blank management */ +#if SEMAPHORE + si->vblank = create_sem(0, di->name); + if (si->vblank < 0) { + result = si->vblank; + goto unmap; + } +#else + /* No semafore for the moment */ + si->vblank = B_ERROR; +#endif + + /* change the owner of the semaphores to the opener's team */ + /* this is required because apps can't aquire kernel semaphores */ +#if SEMAPHORE + thid = find_thread(NULL); + get_thread_info(thid, &thinfo); + set_sem_owner(si->vblank, thinfo.team); +#endif + + /* assign local regs pointer for ATIMACH64xx() macros */ + regs = di->regs; + + /* disable and clear any pending interrupts */ + +#if SEMAPHORE + /* if we're faking interrupts */ + if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){ + /* fake some kind of interrupt with a timer */ + di->can_interrupt = FALSE; + si->flags = SKD_HANDLER_INSTALLED; + si->refresh_period = 16666; /* fake 60Hz to start */ + si->blank_period = si->refresh_period / 20; +#if defined(POST_R4_0) + di->ti_a.di = di; /* refer to ourself */ + di->ti_b.di = di; + di->current_timer = &(di->ti_a); + /* program the first timer interrupt, and it will handle the rest */ + result = add_timer((timer *)(di->current_timer), timer_interrupt_func, si->refresh_period, B_ONE_SHOT_RELATIVE_TIMER); + /* bail if we can't add the timer */ + if (result != B_OK) goto delete_the_sem; +#else */ + /* fake some kind of interrupt with a thread */ + result = di->tid = spawn_kernel_thread(fake_interrupt_thread_func, "SKD fake interrupt", B_REAL_TIME_DISPLAY_PRIORITY, di); + /* bail if we can't spawn the thread */ + if(result < 0) goto delete_the_sem; + /* start up the thread */ + resume_thread(di->tid); + +#endif + } else { + /* otherwise install our interrupt handler */ + result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, atimach64_interrupt, (void *)di, 0); + /* bail if we couldn't install the handler */ + if (result != B_OK) goto delete_the_sem; + } +#endif + + mark_as_open: + /* mark the device open */ + di->is_open++; + + /* send the cookie to the opener */ + *cookie = di; + + goto done; + + /* delete_the_sem: */ + delete_sem(si->vblank); + + /* unmap: */ + unmap_device(di); + + free_shared: + /* clean up our shared area */ + delete_area(di->shared_area); + di->shared_area = -1; + di->si = NULL; + + done: + /* end of critical section */ + RELEASE_BEN(pd->kernel); + + /* all done, return the status */ + ddprintf(("open_hook returning 0x%08lx\n", result)); + + return result; +} + +/* ---------- + read_hook - does nothing, gracefully + ----- */ +static status_t +read_hook (void* dev, off_t pos, void* buf, size_t* len) +{ + *len = 0; + return B_NOT_ALLOWED; +} + + +/* ---------- + write_hook - does nothing, gracefully + ----- */ +static status_t +write_hook (void* dev, off_t pos, const void* buf, size_t* len) +{ + *len = 0; + return B_NOT_ALLOWED; +} + +/* ---------- + close_hook - does nothing, gracefully + ----- */ +static status_t +close_hook (void* dev) +{ + ddprintf(("SKD close_hook(%08lx)\n", (uint32)dev)); + /* we don't do anything on close: there might be dup'd fd */ + return B_NO_ERROR; +} + +/* ----------- + free_hook - close down the device + ----------- */ +static status_t +free_hook (void* dev) { + device_info *di = (device_info *)dev; + shared_info *si = di->si; + + ddprintf(("SKD free_hook() begins...\n")); + /* lock the driver */ + AQUIRE_BEN(pd->kernel); + + /* if opened multiple times, decrement the open count and exit */ + if (di->is_open > 1) + goto unlock_and_exit; + +#if SEMAPHORE + /* disable and clear any pending interrupts */ + + + /* if we were faking the interrupts */ + if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){ + /* stop our interrupt faking thread */ + si->flags = 0; + di->can_interrupt = FALSE; +#if defined(POST_R4_0) + /* cancel the timer */ + /* we don't know which one is current, so cancel them both and ignore any error */ + cancel_timer((timer *)&(di->ti_a)); + cancel_timer((timer *)&(di->ti_b)); +#else + /* we don't do anything here, as the R4 kernel reaps its own threads */ + /* After R4.0 we can do it ourselves, but we'd rather use timers */ +#endif + /* otherwise */ + } else { + /* remove interrupt handler */ + remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, atimach64_interrupt, di); + } + + /* delete the semaphores, ignoring any errors ('cause the owning team may have died on us) */ + delete_sem(si->vblank); +#endif + si->vblank = -1; + + + /* free regs and framebuffer areas */ + unmap_device(di); + + /* clean up our shared area */ + delete_area(di->shared_area); + di->shared_area = -1; + di->si = NULL; + + unlock_and_exit: + /* mark the device available */ + di->is_open--; + /* unlock the driver */ + RELEASE_BEN(pd->kernel); + ddprintf(("SKD free_hook() ends.\n")); + /* all done */ + return B_OK; +} + +/* ----------- + control_hook - where the real work is done + ----------- */ +static status_t +control_hook (void* dev, uint32 msg, void *buf, size_t len) { + device_info *di = (device_info *)dev; + status_t result = B_DEV_INVALID_IOCTL; + + /* ddprintf(("ioctl: %d, buf: 0x%08x, len: %d\n", msg, buf, len));*/ + switch (msg) { + /* the only PUBLIC ioctl */ + case B_GET_ACCELERANT_SIGNATURE: { + char *sig = (char *)buf; + strcpy(sig, "atimach64vt.accelerant"); + result = B_OK; + } break; + + /* PRIVATE ioctl from here on */ + case ATIMACH64_GET_PRIVATE_DATA: { + atimach64_get_private_data *gpd = (atimach64_get_private_data *)buf; + if (gpd->magic == ATIMACH64_PRIVATE_DATA_MAGIC) { + gpd->shared_info_area = di->shared_area; + result = B_OK; + } + } break; + case ATIMACH64_GET_PCI: { + atimach64_get_set_pci *gsp = (atimach64_get_set_pci *)buf; + if (gsp->magic == ATIMACH64_PRIVATE_DATA_MAGIC) { + pci_info *pcii = &(di->pcii); + gsp->value = get_pci(gsp->offset, gsp->size); + result = B_OK; + } + } break; + case ATIMACH64_SET_PCI: { + atimach64_get_set_pci *gsp = (atimach64_get_set_pci *)buf; + if (gsp->magic == ATIMACH64_PRIVATE_DATA_MAGIC) { + pci_info *pcii = &(di->pcii); + set_pci(gsp->offset, gsp->size, gsp->value); + result = B_OK; + } + } break; + case ATIMACH64_RUN_INTERRUPTS: { + atimach64_set_bool_state *ri = (atimach64_set_bool_state *)buf; + if (ri->magic == ATIMACH64_PRIVATE_DATA_MAGIC) { + /* are we faking interrupts? */ + if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){ + di->can_interrupt = ri->do_it; + } else { + vuint32 *regs = di->regs; + if (ri->do_it) { + /* resume interrupts */ + *regs = *regs; /* CHANGE ME */ + } else { + /* disable interrupts */ + *regs = *regs; /* CHANGE ME */ + } + } + result = B_OK; + } + } break; + } + return result; +} diff --git a/src/add-ons/kernel/drivers/graphics/atimach64/m64info.c b/src/add-ons/kernel/drivers/graphics/atimach64/m64info.c new file mode 100644 index 0000000000..a7becf4e3c --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/atimach64/m64info.c @@ -0,0 +1,256 @@ +/* All this code belongs to Linux Xfree86 Project with lots of modifications */ +/* + Rene MacKinney + + 7.May.99 +*/ + +#include +#include "DriverInterface.h" +#include "regmach64.h" +#include "string.h" + +#if DEBUG > 0 +#define ddprintf(a) dprintf a +#else +#define ddprintf(a) +#endif + +status_t +GetATIInfo(si) + shared_info *si; +{ + char signature[] = " 761295520"; + char *bios_data = rommem(0x00); + char bios_signature[10]; + unsigned short *sbios_data = (unsigned short *)bios_data; + int tmp,i,j; + int ROM_Table_Offset; + int Freq_Table_Ptr; + int CDepth_Table_Ptr; + int CTable_Size; + + + if (si->rom == NULL) + return B_ERROR; + + memcpy(bios_signature, rommem(0x30), 10); + + if (strncmp( signature, bios_signature, 10 )) { + ddprintf(("Mach64 probe failed on BIOS signature\n")); + return B_ERROR; + } + + si->board_identifier[0] = bios_data[ 0x40 ]; + si->board_identifier[1] = bios_data[ 0x41 ]; + si->equipment_flags[0] = bios_data[ 0x42 ]; + si->equipment_flags[1] = bios_data[ 0x44 ]; + si->asic_identifier = bios_data[ 0x43 ]; + si->bios_major = bios_data[ 0x4c ]; + si->bios_minor = bios_data[ 0x4d ]; + strncpy( si->bios_date, bios_data + 0x50, 20 ); + + si->VGA_Wonder_Present = bios_data[ 0x44 ] & 0x40; + + si->Mach64_Present = 1; /* Test for Mach64 product */ + + tmp = inw(SCRATCH_REG0); + + + outw(SCRATCH_REG0, 0x55555555); + if (inw(SCRATCH_REG0) != 0x55555555) { + si->Mach64_Present = 0; + ddprintf(("Mach64 probe failed on read 1 of SCRATCH_REG0 %x\n", + SCRATCH_REG0)); + } else { + outw(SCRATCH_REG0, 0xaaaaaaaa); + if (inw(SCRATCH_REG0) != 0xaaaaaaaa) { + si->Mach64_Present = 0; + ddprintf(("Mach64 probe failed on read 2 of SCRATCH_REG0 %x\n", + SCRATCH_REG0)); + } + } + + outw(SCRATCH_REG0, tmp); + + if (!si->Mach64_Present) + return B_ERROR; + + tmp = inw(CONFIG_CHIP_ID); + if (si->device_id != (tmp & CFG_CHIP_TYPE)) { + ddprintf(("%x %x: Mach64 chipset mismatch", + si->device_id, tmp & CFG_CHIP_TYPE)); + return(B_ERROR); + } + + ddprintf(("CONFIG_CHIP_ID reports: %x rev %d\n", + si->device_id, si->revision)); + + tmp = inw(CONFIG_STAT0); + if (si->device_id == MACH64_GX_ID || si->device_id == MACH64_CX_ID) { + si->Bus_Type = tmp & CFG_BUS_TYPE; + si->Mem_Type = (tmp & CFG_MEM_TYPE) >> 3; + si->DAC_Type = (tmp & CFG_INIT_DAC_TYPE) >> 9; + si->DAC_SubType = (inb(SCRATCH_REG1+1) & 0xf0) | si->DAC_Type; + } else { + si->Mem_Type = tmp & CFG_MEM_TYPE_xT; + si->DAC_Type = DAC_INTERNAL; + si->DAC_SubType = DAC_INTERNAL; + + ddprintf(("CONFIG_STAT0 reports mem type %d\n", si->Mem_Type)); + ddprintf(("CONFIG_STAT0 is 0x%08x\n", tmp)); + } + + /* The copy of the registers starts at 0x7ffc00 or 0x3ffc00 depending on the + memory on the card */ + + tmp = inw(MEM_CNTL); + if (si->device_id == MACH64_GX_ID || + si->device_id == MACH64_CX_ID || + si->device_id == MACH64_CT_ID || + si->device_id == MACH64_ET_ID || + ((si->device_id == MACH64_VT_ID || si->device_id == MACH64_GT_ID) && + !(si->revision & 0x07))) { + switch (tmp & MEM_SIZE_ALIAS) { + case MEM_SIZE_512K: + si->mem_size = 512 * 1024; + break; + case MEM_SIZE_1M: + si->mem_size = 1024 * 1024; + break; + case MEM_SIZE_2M: + si->mem_size = 2*1024 * 1024; + break; + case MEM_SIZE_4M: + si->mem_size = 4*1024 * 1024; + break; + case MEM_SIZE_6M: + si->mem_size = 6*1024 * 1024; + break; + case MEM_SIZE_8M: + si->mem_size = 8*1024 * 1024; + break; + } + si->Mem_Size = tmp & MEM_SIZE_ALIAS; + } else { + switch (tmp & MEM_SIZE_ALIAS_GTB) { + case MEM_SIZE_512K: + si->mem_size = 512 * 1024; + break; + case MEM_SIZE_1M: + si->mem_size = 1024 * 1024; + break; + case MEM_SIZE_2M_GTB: + si->mem_size = 2*1024 * 1024; + break; + case MEM_SIZE_4M_GTB: + si->mem_size = 4*1024 * 1024; + break; + case MEM_SIZE_6M_GTB: + si->mem_size = 6*1024 * 1024; + break; + case MEM_SIZE_8M_GTB: + si->mem_size = 8*1024 * 1024; + break; + case MEM_SIZE_16M_GTB: + si->mem_size = 16*1024 * 1024; + break; + } + si->Mem_Size = tmp & MEM_SIZE_ALIAS_GTB; + } + + ddprintf(("Card Reports 0x%08x Memory\n", si->mem_size)); + + ROM_Table_Offset = sbios_data[0x48 >> 1]; + Freq_Table_Ptr = sbios_data[(ROM_Table_Offset >> 1) + 8]; + si->Clock_Type = bios_data[Freq_Table_Ptr]; + + si->MinFreq = sbios_data[(Freq_Table_Ptr >> 1) + 1]; + si->MaxFreq = sbios_data[(Freq_Table_Ptr >> 1) + 2]; + si->RefFreq = sbios_data[(Freq_Table_Ptr >> 1) + 4]; + si->RefDivider = sbios_data[(Freq_Table_Ptr >> 1) + 5]; + si->NAdj = sbios_data[(Freq_Table_Ptr >> 1) + 6]; + si->DRAMMemClk = sbios_data[(Freq_Table_Ptr >> 1) + 8]; + si->VRAMMemClk = sbios_data[(Freq_Table_Ptr >> 1) + 9]; + si->MemClk = bios_data[Freq_Table_Ptr + 22]; + si->CXClk = bios_data[Freq_Table_Ptr + 6]; + + CDepth_Table_Ptr = sbios_data[(Freq_Table_Ptr >> 1) - 3]; + Freq_Table_Ptr = sbios_data[(Freq_Table_Ptr >> 1) - 1]; + + for (i = 0; i < MACH64_NUM_CLOCKS; i++) + si->Clocks[i] = sbios_data[(Freq_Table_Ptr >> 1) + i]; + + si->MemCycle = bios_data[ROM_Table_Offset + 0]; + + CTable_Size = bios_data[CDepth_Table_Ptr - 1]; + for (i = 0, j = 0; + bios_data[CDepth_Table_Ptr + i] != 0; + i += CTable_Size, j++) { + si->Freq_Table[j].h_disp = bios_data[CDepth_Table_Ptr + i]; + si->Freq_Table[j].dacmask = bios_data[CDepth_Table_Ptr + i + 1]; + si->Freq_Table[j].ram_req = bios_data[CDepth_Table_Ptr + i + 2]; + si->Freq_Table[j].max_dot_clock = bios_data[CDepth_Table_Ptr + i + 3]; + si->Freq_Table[j].color_depth = bios_data[CDepth_Table_Ptr + i + 4]; + switch(si->Freq_Table[j].color_depth) { + case 2: /* 8 Bit */ + si->pix_clk_max8 = max(si->pix_clk_max8, si->Freq_Table[j].max_dot_clock); + break; + case 4: /* 16 Bit */ + si->pix_clk_max16 = max(si->pix_clk_max16, si->Freq_Table[j].max_dot_clock); + break; + case 6: /* 8 Bit */ + si->pix_clk_max32 = max(si->pix_clk_max32, si->Freq_Table2[j].max_dot_clock); + break; + } + } + si->Freq_Table[j].h_disp = 0; + + if (bios_data[CDepth_Table_Ptr + i + 1] != 0) { + CDepth_Table_Ptr += i + 2; + CTable_Size = bios_data[CDepth_Table_Ptr - 1]; + for (i = 0, j = 0; + bios_data[CDepth_Table_Ptr + i] != 0; + i += CTable_Size, j++) { + si->Freq_Table2[j].h_disp = bios_data[CDepth_Table_Ptr + i]; + si->Freq_Table2[j].dacmask = bios_data[CDepth_Table_Ptr + i + +1]; + si->Freq_Table2[j].ram_req = bios_data[CDepth_Table_Ptr + i + +2]; + si->Freq_Table2[j].max_dot_clock = bios_data[CDepth_Table_Ptr + i + +3]; + si->Freq_Table2[j].color_depth = bios_data[CDepth_Table_Ptr + i + +4]; + switch(si->Freq_Table[j].color_depth) { + case 2: /* 8 Bit */ + si->pix_clk_max8 = max(si->pix_clk_max8, si->Freq_Table2[j].max_dot_clock); + break; + case 4: /* 16 Bit */ + si->pix_clk_max16 = max(si->pix_clk_max16, si->Freq_Table2[j].max_dot_clock); + break; + case 6: /* 8 Bit */ + si->pix_clk_max32 = max(si->pix_clk_max32, si->Freq_Table2[j].max_dot_clock); + break; + } + } + si->Freq_Table2[j].h_disp = 0; + } else + si->Freq_Table2[0].h_disp = 0; + + /* Hardwired 120000 for 8bpp and 80000 for the rest */ + + ddprintf(("Clocks %ld %ld %ld\n",si->pix_clk_max32, + si->pix_clk_max16, si->pix_clk_max8)); + + + si->pix_clk_max32 = 80000; + si->pix_clk_max16 = 80000; + si->pix_clk_max8 = 120000; + + + ddprintf(("Clocks %ld %ld %ld\n",si->pix_clk_max32, + si->pix_clk_max16, si->pix_clk_max8)); + + + return B_OK; +}