diff --git a/headers/private/graphics/et6x00/DriverInterface.h b/headers/private/graphics/et6x00/DriverInterface.h index 59cf4c44fe..8eda5ba53b 100644 --- a/headers/private/graphics/et6x00/DriverInterface.h +++ b/headers/private/graphics/et6x00/DriverInterface.h @@ -1,123 +1,123 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#ifndef _DRIVERINTERFACE_H_ -#define _DRIVERINTERFACE_H_ - -#include -#include -#include -#include - - -#if defined(__cplusplus) -extern "C" { -#endif - -/* - * This is the info that needs to be shared between the kernel driver and - * the accelerant for the et6000 driver. - */ - -/*****************************************************************************/ -typedef struct { - sem_id sem; - int32 ben; -} benaphore; - -#define INIT_BEN(x) x.sem = create_sem(0, "ET6000 "#x" benaphore"); x.ben = 0; -#define AQUIRE_BEN(x) if((atomic_add(&(x.ben), 1)) >= 1) acquire_sem(x.sem); -#define RELEASE_BEN(x) if((atomic_add(&(x.ben), -1)) > 1) release_sem(x.sem); -#define DELETE_BEN(x) delete_sem(x.sem); -/*****************************************************************************/ -#define ET6000_PRIVATE_DATA_MAGIC 0x100CC001 -/*****************************************************************************/ -#define ET6000_HANDLER_INSTALLED 0x80000000 -/*****************************************************************************/ -/* - * How many bytes of memory the accelerator (ACL) takes from the off-screen - * part of the adapter onboard memory to perform some of its operations. - */ -#define ET6000_ACL_NEEDS_MEMORY 4 -/*****************************************************************************/ -enum { - ET6000_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, - ET6000_GET_PCI, - ET6000_SET_PCI, - ET6000_DEVICE_NAME, - ET6000_PROPOSE_DISPLAY_MODE, - ET6000_SET_DISPLAY_MODE -}; -/*****************************************************************************/ -typedef struct { - uint16 vendor_id; /* PCI vendor ID, from pci_info */ - uint16 device_id; /* PCI device ID, from pci_info */ - uint8 revision; /* PCI device revsion, from pci_info */ - area_id memoryArea; /* Onboard memory's area_id. The addresses - * are shared with all teams. */ - void *framebuffer; /* Start of the mapped framebuffer */ - void *physFramebuffer; /* Physical address of start of framebuffer */ - void *memory; /* Start of the mapped adapter onboard memory */ - void *physMemory; /* Physical address of start of onboard memory */ - uint32 memSize; /* Size of available onboard memory, bytes. */ - uint16 pciConfigSpace; /* PCI header base I/O address */ - void *mmRegs; /* memory mapped registers */ - void *emRegs; /* external mapped registers */ - area_id modesArea; /* Contains the list of display modes the driver supports */ - uint32 modesNum; /* Number of display modes in the list */ - int32 flags; - - display_mode dm; /* current display mode configuration */ - uint8 bytesPerPixel; /* bytes(!) per pixel at current display mode */ - frame_buffer_config fbc; /* bytes_per_row and start of frame buffer */ - - struct { - uint64 count; /* last fifo slot used */ - uint64 lastIdle; /* last fifo slot we *know* the engine was idle after */ - benaphore lock; /* for serializing access to the acceleration engine */ - } engine; - - uint32 pixelClockMax16; /* The maximum speed the pixel clock should run */ - uint32 pixelClockMax24; /* at for a given pixel width. Usually a function */ - /* of memory and DAC bandwidths. */ -} ET6000SharedInfo; -/*****************************************************************************/ -/* Read or write a value in PCI configuration space */ -typedef struct { - uint32 magic; /* magic number to make sure the caller groks us */ - uint32 offset; /* Offset to read/write */ - uint32 size; /* Number of bytes to transfer */ - uint32 value; /* The value read or written */ -} ET6000GetSetPCI; -/*****************************************************************************/ -/* Retrieve the area_id of the kernel/accelerant shared info */ -typedef struct { - uint32 magic; /* magic number to make sure the caller groks us */ - area_id sharedInfoArea; /* area_id containing the shared information */ -} ET6000GetPrivateData; -/*****************************************************************************/ -/* - * Retrieve the device name. Usefull for when we have a file handle, but - * want to know the device name (like when we are cloning the accelerant). - */ -typedef struct { - uint32 magic; /* magic number to make sure the caller groks us */ - char *name; /* The name of the device, less the /dev root */ -} ET6000DeviceName; -/*****************************************************************************/ -typedef struct { - uint32 magic; /* magic number to make sure the caller groks us */ - display_mode mode; /* Proposed mode or mode to set */ - uint16 pciConfigSpace; /* For setting the mode */ - uint32 memSize; /* For proposing the mode */ -} ET6000DisplayMode; -/*****************************************************************************/ - -#if defined(__cplusplus) -} -#endif - - -#endif /* _DRIVERINTERFACE_H_ */ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#ifndef _DRIVERINTERFACE_H_ +#define _DRIVERINTERFACE_H_ + +#include +#include +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * This is the info that needs to be shared between the kernel driver and + * the accelerant for the et6000 driver. + */ + +/*****************************************************************************/ +typedef struct { + sem_id sem; + int32 ben; +} benaphore; + +#define INIT_BEN(x) x.sem = create_sem(0, "ET6000 "#x" benaphore"); x.ben = 0; +#define AQUIRE_BEN(x) if((atomic_add(&(x.ben), 1)) >= 1) acquire_sem(x.sem); +#define RELEASE_BEN(x) if((atomic_add(&(x.ben), -1)) > 1) release_sem(x.sem); +#define DELETE_BEN(x) delete_sem(x.sem); +/*****************************************************************************/ +#define ET6000_PRIVATE_DATA_MAGIC 0x100CC001 +/*****************************************************************************/ +#define ET6000_HANDLER_INSTALLED 0x80000000 +/*****************************************************************************/ +/* + * How many bytes of memory the accelerator (ACL) takes from the off-screen + * part of the adapter onboard memory to perform some of its operations. + */ +#define ET6000_ACL_NEEDS_MEMORY 4 +/*****************************************************************************/ +enum { + ET6000_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, + ET6000_GET_PCI, + ET6000_SET_PCI, + ET6000_DEVICE_NAME, + ET6000_PROPOSE_DISPLAY_MODE, + ET6000_SET_DISPLAY_MODE +}; +/*****************************************************************************/ +typedef struct { + uint16 vendor_id; /* PCI vendor ID, from pci_info */ + uint16 device_id; /* PCI device ID, from pci_info */ + uint8 revision; /* PCI device revsion, from pci_info */ + area_id memoryArea; /* Onboard memory's area_id. The addresses + * are shared with all teams. */ + void *framebuffer; /* Start of the mapped framebuffer */ + void *physFramebuffer; /* Physical address of start of framebuffer */ + void *memory; /* Start of the mapped adapter onboard memory */ + void *physMemory; /* Physical address of start of onboard memory */ + uint32 memSize; /* Size of available onboard memory, bytes. */ + uint16 pciConfigSpace; /* PCI header base I/O address */ + void *mmRegs; /* memory mapped registers */ + void *emRegs; /* external mapped registers */ + area_id modesArea; /* Contains the list of display modes the driver supports */ + uint32 modesNum; /* Number of display modes in the list */ + int32 flags; + + display_mode dm; /* current display mode configuration */ + uint8 bytesPerPixel; /* bytes(!) per pixel at current display mode */ + frame_buffer_config fbc; /* bytes_per_row and start of frame buffer */ + + struct { + uint64 count; /* last fifo slot used */ + uint64 lastIdle; /* last fifo slot we *know* the engine was idle after */ + benaphore lock; /* for serializing access to the acceleration engine */ + } engine; + + uint32 pixelClockMax16; /* The maximum speed the pixel clock should run */ + uint32 pixelClockMax24; /* at for a given pixel width. Usually a function */ + /* of memory and DAC bandwidths. */ +} ET6000SharedInfo; +/*****************************************************************************/ +/* Read or write a value in PCI configuration space */ +typedef struct { + uint32 magic; /* magic number to make sure the caller groks us */ + uint32 offset; /* Offset to read/write */ + uint32 size; /* Number of bytes to transfer */ + uint32 value; /* The value read or written */ +} ET6000GetSetPCI; +/*****************************************************************************/ +/* Retrieve the area_id of the kernel/accelerant shared info */ +typedef struct { + uint32 magic; /* magic number to make sure the caller groks us */ + area_id sharedInfoArea; /* area_id containing the shared information */ +} ET6000GetPrivateData; +/*****************************************************************************/ +/* + * Retrieve the device name. Usefull for when we have a file handle, but + * want to know the device name (like when we are cloning the accelerant). + */ +typedef struct { + uint32 magic; /* magic number to make sure the caller groks us */ + char *name; /* The name of the device, less the /dev root */ +} ET6000DeviceName; +/*****************************************************************************/ +typedef struct { + uint32 magic; /* magic number to make sure the caller groks us */ + display_mode mode; /* Proposed mode or mode to set */ + uint16 pciConfigSpace; /* For setting the mode */ + uint32 memSize; /* For proposing the mode */ +} ET6000DisplayMode; +/*****************************************************************************/ + +#if defined(__cplusplus) +} +#endif + + +#endif /* _DRIVERINTERFACE_H_ */ diff --git a/src/add-ons/accelerants/et6x00/Acceleration.c b/src/add-ons/accelerants/et6x00/Acceleration.c index 26b6f3a0c8..c1f46a827d 100644 --- a/src/add-ons/accelerants/et6x00/Acceleration.c +++ b/src/add-ons/accelerants/et6x00/Acceleration.c @@ -1,256 +1,256 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#include "GlobalData.h" -#include "generic.h" - - -/*****************************************************************************/ -/* - * Set bits in a byte pointed by addr; mask must contain 0s at the bits - * positions to be set and must contain 1s at all other bits; val must - * contain the values of bits to be set. - */ -__inline void set8(volatile char *addr, char mask, char val) -{ - if (mask == 0) - *addr = val; - else - *addr = (*addr & mask) | (val & ~mask); -} -/*****************************************************************************/ -__inline char get8(volatile char *addr) -{ - return *addr; -} -/*****************************************************************************/ -__inline void et6000aclTerminate(void) { - set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */ - et6000aclWaitIdle(); - set8(mmRegs+0x30, 0, 0x00); - set8(mmRegs+0x30, 0, 0x01); - et6000aclWaitIdle(); - set8(mmRegs+0x30, 0, 0x00); - set8(mmRegs+0x30, 0, 0x10); - et6000aclWaitIdle(); - set8(mmRegs+0x30, 0, 0x00); -} -/*****************************************************************************/ -/* - * bpp must be bytes per pixel, not bits! - */ -void et6000aclInit(uint8 bpp) { - - et6000aclTerminate(); - - set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */ - set8(mmRegs+0x32, 0x99, 0x00); /* maximize the performance */ - set8(mmRegs+0x8e, 0xcf, (bpp - 1) << 4); /* set pixel color depth */ - set8(mmRegs+0x91, 0x80, 0x00); /* maximize the performance */ - set8(mmRegs+0x9d, 0x00, 0x00); /* maximize the performance */ -} -/*****************************************************************************/ -/* - * Wait until ACL becomes idle. - */ -void et6000aclWaitIdle(void) { - while ((get8(mmRegs+0x36) & 0x02) == 0x02); -} -/*****************************************************************************/ -/* - * Wait until ACL queue becomes not full. - */ -__inline void et6000aclWaitQueueNotFull(void) { - while ((get8(mmRegs+0x36) & 0x01) == 0x01); -} -/*****************************************************************************/ -/* - * Move the specified list of rectangular regions from one location in - * the frame buffer to another in the order they are specified in the - * blit_params *list. The list is uint32 count elements in length. - */ -void SCREEN_TO_SCREEN_BLIT(engine_token *et, - blit_params *list, - uint32 count) -{ -uint16 screenWidth = si->dm.virtual_width; -uint8 bpp = si->bytesPerPixel; -uint8 bltDir; -uint16 src_left, src_top, dest_left, dest_top, width, height; -uint32 srcAddr, destAddr; - - et6000aclWaitQueueNotFull(); - - set8(mmRegs+0x92, 0x80, 0x77); /* no source wrap */ - set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */ - set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */ - - /* Set the source Y offset */ - *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1; - - /* Set the destination Y offset */ - *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1; - - 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; - height = list->height; - - et6000aclWaitQueueNotFull(); - - /* Set the direction and opcode(BitBLT) register */ - bltDir = 0x00; - if (src_left < dest_left) bltDir |= 0x01; - if (src_top < dest_top) bltDir |= 0x02; - set8(mmRegs+0x8f, 0x3c, bltDir); - - /* Set the X count register */ - *((vuint16 *)(mmRegs+0x98)) = (width + 1) * bpp - 1; - - /* Set the Y count register */ - *((vuint16 *)(mmRegs+0x9a)) = height; - - switch (bltDir & 0x03) { - case 0x00: - srcAddr = (src_top * screenWidth + src_left) * bpp; - destAddr = (dest_top * screenWidth + dest_left) * bpp; - break; - - case 0x01: - srcAddr = (src_top * screenWidth + src_left + width) * bpp + bpp-1; - destAddr = (dest_top * screenWidth + dest_left + width) * bpp + bpp-1; - break; - - case 0x02: - srcAddr = ((src_top + height)*screenWidth + src_left) * bpp; - destAddr = ((dest_top + height)*screenWidth + dest_left) * bpp; - break; - - case 0x03: - srcAddr = ((src_top + height)*screenWidth + src_left + width) * bpp + bpp-1; - destAddr = ((dest_top + height)*screenWidth + dest_left + width) * bpp + bpp-1; - break; - } - - /* Set the source address */ - *((vuint32 *)(mmRegs+0x84)) = srcAddr; - - /* - * Set the destination address - - * this action starts the BitBLT operation. - */ - *((vuint32 *)(mmRegs+0xa0)) = destAddr; - - list++; - } - - si->engine.count++; -} -/*****************************************************************************/ -/* - * Fill the specified list of rectangular regions with the specified color. - * The list is uint32 count elements in length. The rectangular regions are - * inclusive. The uint32 color is specified in the same configuration and - * byte order as the current display_mode. All coordinates in the list of - * rectangles is guaranteed to have been clipped to the virtual limits of - * the display_mode. - */ -void FILL_RECTANGLE(engine_token *et, - uint32 color, - fill_rect_params *list, - uint32 count) -{ -uint16 screenWidth = si->dm.virtual_width; -uint8 bpp = si->bytesPerPixel; -uint16 left, top, right, bottom; -uint32 srcAddr; -uint8 i; - - /* - * Normally WaitQueueNotFull should be required & enough, but in reality - * this is somewhy sometimes not enough for pixel depth of 3 bytes. - */ - if (bpp == 2) - et6000aclWaitQueueNotFull(); - else - et6000aclWaitIdle(); - - /* - * We'll put the color at 4 bytes just after the framebuffer. - * The srcAddr must be 4 bytes aligned and is always for standard - * resolutions. - */ - srcAddr = (uint32)si->framebuffer - (uint32)si->memory + - si->dm.virtual_width * si->dm.virtual_height * bpp; - - switch(bpp) { - case 2: - set8(mmRegs+0x92, 0x80, 0x02); /* 4x1 source wrap */ - for (i = 0; i < 2; i++) /* copy the color to source address */ - ((vuint16 *)((uint32)si->memory + srcAddr))[i] = (uint16)color; - break; - case 3: - set8(mmRegs+0x92, 0x80, 0x0a); /* 3x1 source wrap */ - for (i = 0; i < 3; i++) /* copy the color to source address */ - ((vuint8 *)((uint32)si->memory + srcAddr))[i] = ((uint8 *)&color)[i]; - - break; - } - - set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */ - set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */ - - /* Set the source Y offset */ - *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1; - /* Set the destination Y offset */ - *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1; - - /* Set the direction and opcode(trapezoid) register (primary edge) */ - set8(mmRegs+0x8f, 0x18, 0x40); - /* Set the secondary edge register */ - set8(mmRegs+0x93, 0x1a, 0x00); - - /* Set the primary delta minor register */ - *((vuint16 *)(mmRegs+0xac)) = 0; - /* Set the secondary delta minor register */ - *((vuint16 *)(mmRegs+0xb4)) = 0; - - while(count--) { - left = list->left; - top = list->top; - right = list->right; - bottom = list->bottom; - - et6000aclWaitQueueNotFull(); - - /* Set the X count register */ - *((vuint16 *)(mmRegs+0x98)) = (right-left+1)*bpp - 1; - /* Set the Y count register */ - *((vuint16 *)(mmRegs+0x9a)) = bottom-top; - - /* Set the primary delta major register */ - *((vuint16 *)(mmRegs+0xae)) = bottom-top; - - /* Set the secondary delta major register */ - *((vuint16 *)(mmRegs+0xb6)) = bottom-top; - - /* Set the source address */ - *((vuint32 *)(mmRegs+0x84)) = srcAddr; - - /* - * Set the destination address - - * this action starts the trapezoid operation. - */ - *((vuint32 *)(mmRegs+0xa0)) = (top * screenWidth + left) * bpp; - - list++; - } - - si->engine.count++; -} -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#include "GlobalData.h" +#include "generic.h" + + +/*****************************************************************************/ +/* + * Set bits in a byte pointed by addr; mask must contain 0s at the bits + * positions to be set and must contain 1s at all other bits; val must + * contain the values of bits to be set. + */ +__inline void set8(volatile char *addr, char mask, char val) +{ + if (mask == 0) + *addr = val; + else + *addr = (*addr & mask) | (val & ~mask); +} +/*****************************************************************************/ +__inline char get8(volatile char *addr) +{ + return *addr; +} +/*****************************************************************************/ +__inline void et6000aclTerminate(void) { + set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */ + et6000aclWaitIdle(); + set8(mmRegs+0x30, 0, 0x00); + set8(mmRegs+0x30, 0, 0x01); + et6000aclWaitIdle(); + set8(mmRegs+0x30, 0, 0x00); + set8(mmRegs+0x30, 0, 0x10); + et6000aclWaitIdle(); + set8(mmRegs+0x30, 0, 0x00); +} +/*****************************************************************************/ +/* + * bpp must be bytes per pixel, not bits! + */ +void et6000aclInit(uint8 bpp) { + + et6000aclTerminate(); + + set8(mmRegs+0x31, 0xef, 0x10); /* let ACL to operate */ + set8(mmRegs+0x32, 0x99, 0x00); /* maximize the performance */ + set8(mmRegs+0x8e, 0xcf, (bpp - 1) << 4); /* set pixel color depth */ + set8(mmRegs+0x91, 0x80, 0x00); /* maximize the performance */ + set8(mmRegs+0x9d, 0x00, 0x00); /* maximize the performance */ +} +/*****************************************************************************/ +/* + * Wait until ACL becomes idle. + */ +void et6000aclWaitIdle(void) { + while ((get8(mmRegs+0x36) & 0x02) == 0x02); +} +/*****************************************************************************/ +/* + * Wait until ACL queue becomes not full. + */ +__inline void et6000aclWaitQueueNotFull(void) { + while ((get8(mmRegs+0x36) & 0x01) == 0x01); +} +/*****************************************************************************/ +/* + * Move the specified list of rectangular regions from one location in + * the frame buffer to another in the order they are specified in the + * blit_params *list. The list is uint32 count elements in length. + */ +void SCREEN_TO_SCREEN_BLIT(engine_token *et, + blit_params *list, + uint32 count) +{ +uint16 screenWidth = si->dm.virtual_width; +uint8 bpp = si->bytesPerPixel; +uint8 bltDir; +uint16 src_left, src_top, dest_left, dest_top, width, height; +uint32 srcAddr, destAddr; + + et6000aclWaitQueueNotFull(); + + set8(mmRegs+0x92, 0x80, 0x77); /* no source wrap */ + set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */ + set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */ + + /* Set the source Y offset */ + *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1; + + /* Set the destination Y offset */ + *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1; + + 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; + height = list->height; + + et6000aclWaitQueueNotFull(); + + /* Set the direction and opcode(BitBLT) register */ + bltDir = 0x00; + if (src_left < dest_left) bltDir |= 0x01; + if (src_top < dest_top) bltDir |= 0x02; + set8(mmRegs+0x8f, 0x3c, bltDir); + + /* Set the X count register */ + *((vuint16 *)(mmRegs+0x98)) = (width + 1) * bpp - 1; + + /* Set the Y count register */ + *((vuint16 *)(mmRegs+0x9a)) = height; + + switch (bltDir & 0x03) { + case 0x00: + srcAddr = (src_top * screenWidth + src_left) * bpp; + destAddr = (dest_top * screenWidth + dest_left) * bpp; + break; + + case 0x01: + srcAddr = (src_top * screenWidth + src_left + width) * bpp + bpp-1; + destAddr = (dest_top * screenWidth + dest_left + width) * bpp + bpp-1; + break; + + case 0x02: + srcAddr = ((src_top + height)*screenWidth + src_left) * bpp; + destAddr = ((dest_top + height)*screenWidth + dest_left) * bpp; + break; + + case 0x03: + srcAddr = ((src_top + height)*screenWidth + src_left + width) * bpp + bpp-1; + destAddr = ((dest_top + height)*screenWidth + dest_left + width) * bpp + bpp-1; + break; + } + + /* Set the source address */ + *((vuint32 *)(mmRegs+0x84)) = srcAddr; + + /* + * Set the destination address - + * this action starts the BitBLT operation. + */ + *((vuint32 *)(mmRegs+0xa0)) = destAddr; + + list++; + } + + si->engine.count++; +} +/*****************************************************************************/ +/* + * Fill the specified list of rectangular regions with the specified color. + * The list is uint32 count elements in length. The rectangular regions are + * inclusive. The uint32 color is specified in the same configuration and + * byte order as the current display_mode. All coordinates in the list of + * rectangles is guaranteed to have been clipped to the virtual limits of + * the display_mode. + */ +void FILL_RECTANGLE(engine_token *et, + uint32 color, + fill_rect_params *list, + uint32 count) +{ +uint16 screenWidth = si->dm.virtual_width; +uint8 bpp = si->bytesPerPixel; +uint16 left, top, right, bottom; +uint32 srcAddr; +uint8 i; + + /* + * Normally WaitQueueNotFull should be required & enough, but in reality + * this is somewhy sometimes not enough for pixel depth of 3 bytes. + */ + if (bpp == 2) + et6000aclWaitQueueNotFull(); + else + et6000aclWaitIdle(); + + /* + * We'll put the color at 4 bytes just after the framebuffer. + * The srcAddr must be 4 bytes aligned and is always for standard + * resolutions. + */ + srcAddr = (uint32)si->framebuffer - (uint32)si->memory + + si->dm.virtual_width * si->dm.virtual_height * bpp; + + switch(bpp) { + case 2: + set8(mmRegs+0x92, 0x80, 0x02); /* 4x1 source wrap */ + for (i = 0; i < 2; i++) /* copy the color to source address */ + ((vuint16 *)((uint32)si->memory + srcAddr))[i] = (uint16)color; + break; + case 3: + set8(mmRegs+0x92, 0x80, 0x0a); /* 3x1 source wrap */ + for (i = 0; i < 3; i++) /* copy the color to source address */ + ((vuint8 *)((uint32)si->memory + srcAddr))[i] = ((uint8 *)&color)[i]; + + break; + } + + set8(mmRegs+0x9c, 0x00, 0x33); /* mask=1 always, always use FGR */ + set8(mmRegs+0x9f, 0x00, 0xcc); /* FGR ROP = copy of source */ + + /* Set the source Y offset */ + *((vuint16 *)(mmRegs+0x8a)) = screenWidth * bpp - 1; + /* Set the destination Y offset */ + *((vuint16 *)(mmRegs+0x8c)) = screenWidth * bpp - 1; + + /* Set the direction and opcode(trapezoid) register (primary edge) */ + set8(mmRegs+0x8f, 0x18, 0x40); + /* Set the secondary edge register */ + set8(mmRegs+0x93, 0x1a, 0x00); + + /* Set the primary delta minor register */ + *((vuint16 *)(mmRegs+0xac)) = 0; + /* Set the secondary delta minor register */ + *((vuint16 *)(mmRegs+0xb4)) = 0; + + while(count--) { + left = list->left; + top = list->top; + right = list->right; + bottom = list->bottom; + + et6000aclWaitQueueNotFull(); + + /* Set the X count register */ + *((vuint16 *)(mmRegs+0x98)) = (right-left+1)*bpp - 1; + /* Set the Y count register */ + *((vuint16 *)(mmRegs+0x9a)) = bottom-top; + + /* Set the primary delta major register */ + *((vuint16 *)(mmRegs+0xae)) = bottom-top; + + /* Set the secondary delta major register */ + *((vuint16 *)(mmRegs+0xb6)) = bottom-top; + + /* Set the source address */ + *((vuint32 *)(mmRegs+0x84)) = srcAddr; + + /* + * Set the destination address - + * this action starts the trapezoid operation. + */ + *((vuint32 *)(mmRegs+0xa0)) = (top * screenWidth + left) * bpp; + + list++; + } + + si->engine.count++; +} +/*****************************************************************************/ diff --git a/src/add-ons/accelerants/et6x00/GlobalData.c b/src/add-ons/accelerants/et6x00/GlobalData.c index 19df417ee1..d00dc5691f 100644 --- a/src/add-ons/accelerants/et6x00/GlobalData.c +++ b/src/add-ons/accelerants/et6x00/GlobalData.c @@ -1,17 +1,17 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#include "GlobalData.h" - - -/*****************************************************************************/ -int fd; -ET6000SharedInfo *si; -area_id sharedInfoArea; -display_mode *et6000ModesList; -area_id et6000ModesListArea; -int accelerantIsClone; -volatile unsigned char *mmRegs; /* memory mapped registers */ -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#include "GlobalData.h" + + +/*****************************************************************************/ +int fd; +ET6000SharedInfo *si; +area_id sharedInfoArea; +display_mode *et6000ModesList; +area_id et6000ModesListArea; +int accelerantIsClone; +volatile unsigned char *mmRegs; /* memory mapped registers */ +/*****************************************************************************/ diff --git a/src/add-ons/accelerants/et6x00/GlobalData.h b/src/add-ons/accelerants/et6x00/GlobalData.h index cbda3d9a53..038cf453dd 100644 --- a/src/add-ons/accelerants/et6x00/GlobalData.h +++ b/src/add-ons/accelerants/et6x00/GlobalData.h @@ -1,23 +1,23 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#ifndef _ET6000GLOBALDATA_H_ -#define _ET6000GLOBALDATA_H_ - -#include "DriverInterface.h" - - -/*****************************************************************************/ -extern int fd; -extern ET6000SharedInfo *si; -extern area_id sharedInfoArea; -extern display_mode *et6000ModesList; -extern area_id et6000ModesListArea; -extern int accelerantIsClone; -extern volatile unsigned char *mmRegs; /* memory mapped registers */ -/*****************************************************************************/ - - -#endif /* _ET6000GLOBALDATA_H_ */ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#ifndef _ET6000GLOBALDATA_H_ +#define _ET6000GLOBALDATA_H_ + +#include "DriverInterface.h" + + +/*****************************************************************************/ +extern int fd; +extern ET6000SharedInfo *si; +extern area_id sharedInfoArea; +extern display_mode *et6000ModesList; +extern area_id et6000ModesListArea; +extern int accelerantIsClone; +extern volatile unsigned char *mmRegs; /* memory mapped registers */ +/*****************************************************************************/ + + +#endif /* _ET6000GLOBALDATA_H_ */ diff --git a/src/add-ons/accelerants/et6x00/InitAccelerant.c b/src/add-ons/accelerants/et6x00/InitAccelerant.c index bf1a6f5c3d..65df0bc04c 100644 --- a/src/add-ons/accelerants/et6x00/InitAccelerant.c +++ b/src/add-ons/accelerants/et6x00/InitAccelerant.c @@ -1,227 +1,227 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#include "GlobalData.h" -#include "generic.h" - -#include "string.h" -#include "unistd.h" -#include "sys/types.h" -#include "sys/stat.h" -#include "fcntl.h" -#include - - -/*****************************************************************************/ -/* - * Initialization code shared between primary and cloned accelerants. - */ -static status_t initCommon(int the_fd) { -status_t result; -ET6000GetPrivateData gpd; - - /* memorize the file descriptor */ - fd = the_fd; - /* set the magic number so the driver knows we're for real */ - gpd.magic = ET6000_PRIVATE_DATA_MAGIC; - /* contact driver and get a pointer to the registers and shared data */ - result = ioctl(fd, ET6000_GET_PRIVATE_DATA, &gpd, sizeof(gpd)); - if (result != B_OK) goto error0; - - /* clone the shared area for our use */ - sharedInfoArea = clone_area("ET6000 shared info", (void **)&si, - B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gpd.sharedInfoArea); - if (sharedInfoArea < 0) { - result = sharedInfoArea; - goto error0; - } - - mmRegs = si->mmRegs; - -error0: - return result; -} -/*****************************************************************************/ -/* - * Clean up code shared between primary and cloned accelrants. - */ -static void uninitCommon(void) { - /* release our copy of the shared info from the kernel driver */ - delete_area(sharedInfoArea); - 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 = initCommon(the_fd); - - /* bail out if the common initialization failed */ - if (result != B_OK) goto error0; - - /* Call the device specific initialization code here, bail out if it failed */ - if (result != B_OK) goto error1; - - /* - * Now is a good time to figure out what video modes the 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 = createModesList(); - if (result != B_OK) goto error2; - - /* - * 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 = si->framebuffer; - si->fbc.frame_buffer_dma = si->physFramebuffer; - - /* init the shared semaphore */ - INIT_BEN(si->engine.lock); - - /* initialize the engine synchronization variables */ - - /* count of issued parameters or commands */ - si->engine.lastIdle = si->engine.count = 0; - - /* bail out if something failed */ - if (result != B_OK) goto error3; - - /* 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 initCommon() succeeded, so we need to - * clean up before quiting. - */ - uninitCommon(); - -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 B_OS_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) { -ET6000DeviceName dn; -status_t result; - - /* call the kernel driver to get the device name */ - dn.magic = ET6000_PRIVATE_DATA_MAGIC; - /* store the returned info directly into the passed buffer */ - dn.name = (char *)data; - result = ioctl(fd, ET6000_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 = initCommon(fd); - - /* bail out if the common initialization failed */ - if (result != B_OK) goto error1; - - /* get shared area for display modes */ - result = et6000ModesListArea = clone_area("ET6000 cloned display_modes", - (void **)&et6000ModesList, B_ANY_ADDRESS, B_READ_AREA, si->modesArea); - if (result < B_OK) goto error2; - - /* all done */ - result = B_OK; - goto error0; - -error2: - /* free up the areas we cloned */ - uninitCommon(); -error1: - /* close the device we opened */ - close(fd); -error0: - return result; -} -/*****************************************************************************/ -void UNINIT_ACCELERANT(void) { - /* free our mode list area */ - delete_area(et6000ModesListArea); - et6000ModesList = 0; - - /* release our cloned data */ - uninitCommon(); - - /* close the file handle ONLY if we're the clone */ - if (accelerantIsClone) close(fd); -} -/*****************************************************************************/ -status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi) -{ - adi->version = B_ACCELERANT_VERSION; - strcpy(adi->name, "Tseng Labs ET6x00"); - strcpy(adi->chipset, "Tseng Labs ET6x00"); - strcpy(adi->serial_no, ""); - adi->memory = si->memSize; - adi->dac_speed = si->pixelClockMax16; - - return B_OK; -} -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#include "GlobalData.h" +#include "generic.h" + +#include "string.h" +#include "unistd.h" +#include "sys/types.h" +#include "sys/stat.h" +#include "fcntl.h" +#include + + +/*****************************************************************************/ +/* + * Initialization code shared between primary and cloned accelerants. + */ +static status_t initCommon(int the_fd) { +status_t result; +ET6000GetPrivateData gpd; + + /* memorize the file descriptor */ + fd = the_fd; + /* set the magic number so the driver knows we're for real */ + gpd.magic = ET6000_PRIVATE_DATA_MAGIC; + /* contact driver and get a pointer to the registers and shared data */ + result = ioctl(fd, ET6000_GET_PRIVATE_DATA, &gpd, sizeof(gpd)); + if (result != B_OK) goto error0; + + /* clone the shared area for our use */ + sharedInfoArea = clone_area("ET6000 shared info", (void **)&si, + B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gpd.sharedInfoArea); + if (sharedInfoArea < 0) { + result = sharedInfoArea; + goto error0; + } + + mmRegs = si->mmRegs; + +error0: + return result; +} +/*****************************************************************************/ +/* + * Clean up code shared between primary and cloned accelrants. + */ +static void uninitCommon(void) { + /* release our copy of the shared info from the kernel driver */ + delete_area(sharedInfoArea); + 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 = initCommon(the_fd); + + /* bail out if the common initialization failed */ + if (result != B_OK) goto error0; + + /* Call the device specific initialization code here, bail out if it failed */ + if (result != B_OK) goto error1; + + /* + * Now is a good time to figure out what video modes the 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 = createModesList(); + if (result != B_OK) goto error2; + + /* + * 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 = si->framebuffer; + si->fbc.frame_buffer_dma = si->physFramebuffer; + + /* init the shared semaphore */ + INIT_BEN(si->engine.lock); + + /* initialize the engine synchronization variables */ + + /* count of issued parameters or commands */ + si->engine.lastIdle = si->engine.count = 0; + + /* bail out if something failed */ + if (result != B_OK) goto error3; + + /* 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 initCommon() succeeded, so we need to + * clean up before quiting. + */ + uninitCommon(); + +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 B_OS_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) { +ET6000DeviceName dn; +status_t result; + + /* call the kernel driver to get the device name */ + dn.magic = ET6000_PRIVATE_DATA_MAGIC; + /* store the returned info directly into the passed buffer */ + dn.name = (char *)data; + result = ioctl(fd, ET6000_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 = initCommon(fd); + + /* bail out if the common initialization failed */ + if (result != B_OK) goto error1; + + /* get shared area for display modes */ + result = et6000ModesListArea = clone_area("ET6000 cloned display_modes", + (void **)&et6000ModesList, B_ANY_ADDRESS, B_READ_AREA, si->modesArea); + if (result < B_OK) goto error2; + + /* all done */ + result = B_OK; + goto error0; + +error2: + /* free up the areas we cloned */ + uninitCommon(); +error1: + /* close the device we opened */ + close(fd); +error0: + return result; +} +/*****************************************************************************/ +void UNINIT_ACCELERANT(void) { + /* free our mode list area */ + delete_area(et6000ModesListArea); + et6000ModesList = 0; + + /* release our cloned data */ + uninitCommon(); + + /* close the file handle ONLY if we're the clone */ + if (accelerantIsClone) close(fd); +} +/*****************************************************************************/ +status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi) +{ + adi->version = B_ACCELERANT_VERSION; + strcpy(adi->name, "Tseng Labs ET6x00"); + strcpy(adi->chipset, "Tseng Labs ET6x00"); + strcpy(adi->serial_no, ""); + adi->memory = si->memSize; + adi->dac_speed = si->pixelClockMax16; + + return B_OK; +} +/*****************************************************************************/ diff --git a/src/add-ons/accelerants/et6x00/ProposeDisplayMode.c b/src/add-ons/accelerants/et6x00/ProposeDisplayMode.c index 40a9342b65..3e478b292b 100644 --- a/src/add-ons/accelerants/et6x00/ProposeDisplayMode.c +++ b/src/add-ons/accelerants/et6x00/ProposeDisplayMode.c @@ -1,141 +1,141 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#include "GlobalData.h" -#include "generic.h" -#include -#include - - -/*****************************************************************************/ -#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) -#define MODE_FLAGS (B_SCROLL | B_8_BIT_DAC | B_PARALLEL_ACCESS) -#define MODE_COUNT (sizeof (modesList) / sizeof (display_mode)) -/*****************************************************************************/ -static const display_mode modesList[] = { -{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */ -{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */ -{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */ -{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */ -{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */ -{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */ -{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */ -{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */ -{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */ -{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_RGB24, 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_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */ -{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */ -{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_RGB24, 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_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */ -{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */ -{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */ -{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */ -{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */ -{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */ -{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */ -{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */ -{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */ -{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */ -{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */ -{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */ -{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */ -{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */ -}; -/*****************************************************************************/ -/* - * 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) -{ -ET6000DisplayMode mode; - - mode.magic = ET6000_PRIVATE_DATA_MAGIC; - mode.mode = *target; - mode.memSize = si->memSize; - - return ioctl(fd, ET6000_PROPOSE_DISPLAY_MODE, &mode, sizeof(mode)); -} -/*****************************************************************************/ -/* - * 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->modesNum; -} -/*****************************************************************************/ -/* - * 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, et6000ModesList, si->modesNum * sizeof(display_mode)); - return B_OK; -} -/*****************************************************************************/ -/* - * Create a list of display_modes to pass back to the caller. - */ -status_t createModesList(void) { -size_t maxSize; -uint32 i, j, pixelClockRange; -const display_mode *src; -display_mode *dst, low, high; -color_space spaces[] = {B_RGB15_LITTLE, B_RGB16_LITTLE, B_RGB24_LITTLE}; - - - /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */ - maxSize = (((MODE_COUNT * 3) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1); - - /* Create an area to hold the info */ - si->modesArea = et6000ModesListArea = - create_area("ET6000 accelerant mode info", (void **)&et6000ModesList, - B_ANY_ADDRESS, maxSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - - if (et6000ModesListArea < B_OK) - return et6000ModesListArea; - - /* walk through our predefined list and see which modes fit this device */ - src = modesList; - dst = et6000ModesList; - si->modesNum = 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 */ - pixelClockRange = low.timing.pixel_clock >> 5; - low.timing.pixel_clock -= pixelClockRange; - high.timing.pixel_clock += pixelClockRange; - /* 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->modesNum++; - } - } - /* advance to next mode */ - src++; - } - - return B_OK; -} -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#include "GlobalData.h" +#include "generic.h" +#include +#include + + +/*****************************************************************************/ +#define T_POSITIVE_SYNC (B_POSITIVE_HSYNC | B_POSITIVE_VSYNC) +#define MODE_FLAGS (B_SCROLL | B_8_BIT_DAC | B_PARALLEL_ACCESS) +#define MODE_COUNT (sizeof (modesList) / sizeof (display_mode)) +/*****************************************************************************/ +static const display_mode modesList[] = { +{ { 25175, 640, 656, 752, 800, 480, 490, 492, 525, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(640X480X8.Z1) */ +{ { 27500, 640, 672, 768, 864, 480, 488, 494, 530, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* 640X480X60Hz */ +{ { 30500, 640, 672, 768, 864, 480, 517, 523, 588, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* SVGA_640X480X60HzNI */ +{ { 31500, 640, 664, 704, 832, 480, 489, 492, 520, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70-72Hz_(640X480X8.Z1) */ +{ { 31500, 640, 656, 720, 840, 480, 481, 484, 500, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(640X480X8.Z1) */ +{ { 36000, 640, 696, 752, 832, 480, 481, 484, 509, 0}, B_RGB24, 640, 480, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(640X480X8.Z1) */ +{ { 38100, 800, 832, 960, 1088, 600, 602, 606, 620, 0}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* SVGA_800X600X56HzNI */ +{ { 40000, 800, 840, 968, 1056, 600, 601, 605, 628, T_POSITIVE_SYNC}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(800X600X8.Z1) */ +{ { 49500, 800, 816, 896, 1056, 600, 601, 604, 625, T_POSITIVE_SYNC}, B_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(800X600X8.Z1) */ +{ { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, T_POSITIVE_SYNC}, B_RGB24, 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_RGB24, 800, 600, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(800X600X8.Z1) */ +{ { 65000, 1024, 1048, 1184, 1344, 768, 771, 777, 806, 0}, B_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1024X768X8.Z1) */ +{ { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 0}, B_RGB24, 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_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1024X768X8.Z1) */ +{ { 94500, 1024, 1072, 1168, 1376, 768, 769, 772, 808, T_POSITIVE_SYNC}, B_RGB24, 1024, 768, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1024X768X8.Z1) */ +{ { 94200, 1152, 1184, 1280, 1472, 864, 865, 868, 914, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1152X864X8.Z1) */ +{ { 108000, 1152, 1216, 1344, 1600, 864, 865, 868, 900, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1152X864X8.Z1) */ +{ { 121500, 1152, 1216, 1344, 1568, 864, 865, 868, 911, T_POSITIVE_SYNC}, B_RGB24, 1152, 864, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1152X864X8.Z1) */ +{ { 108000, 1280, 1328, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1280X1024X8.Z1) */ +{ { 135000, 1280, 1296, 1440, 1688, 1024, 1025, 1028, 1066, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1280X1024X8.Z1) */ +{ { 157500, 1280, 1344, 1504, 1728, 1024, 1025, 1028, 1072, T_POSITIVE_SYNC}, B_RGB24, 1280, 1024, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@85Hz_(1280X1024X8.Z1) */ +{ { 162000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@60Hz_(1600X1200X8.Z1) */ +{ { 175500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@65Hz_(1600X1200X8.Z1) */ +{ { 189000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@70Hz_(1600X1200X8.Z1) */ +{ { 202500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@75Hz_(1600X1200X8.Z1) */ +{ { 216000, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS}, /* Vesa_Monitor_@80Hz_(1600X1200X8.Z1) */ +{ { 229500, 1600, 1664, 1856, 2160, 1200, 1201, 1204, 1250, T_POSITIVE_SYNC}, B_RGB24, 1600, 1200, 0, 0, MODE_FLAGS} /* Vesa_Monitor_@85Hz_(1600X1200X8.Z1) */ +}; +/*****************************************************************************/ +/* + * 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) +{ +ET6000DisplayMode mode; + + mode.magic = ET6000_PRIVATE_DATA_MAGIC; + mode.mode = *target; + mode.memSize = si->memSize; + + return ioctl(fd, ET6000_PROPOSE_DISPLAY_MODE, &mode, sizeof(mode)); +} +/*****************************************************************************/ +/* + * 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->modesNum; +} +/*****************************************************************************/ +/* + * 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, et6000ModesList, si->modesNum * sizeof(display_mode)); + return B_OK; +} +/*****************************************************************************/ +/* + * Create a list of display_modes to pass back to the caller. + */ +status_t createModesList(void) { +size_t maxSize; +uint32 i, j, pixelClockRange; +const display_mode *src; +display_mode *dst, low, high; +color_space spaces[] = {B_RGB15_LITTLE, B_RGB16_LITTLE, B_RGB24_LITTLE}; + + + /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */ + maxSize = (((MODE_COUNT * 3) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1); + + /* Create an area to hold the info */ + si->modesArea = et6000ModesListArea = + create_area("ET6000 accelerant mode info", (void **)&et6000ModesList, + B_ANY_ADDRESS, maxSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); + + if (et6000ModesListArea < B_OK) + return et6000ModesListArea; + + /* walk through our predefined list and see which modes fit this device */ + src = modesList; + dst = et6000ModesList; + si->modesNum = 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 */ + pixelClockRange = low.timing.pixel_clock >> 5; + low.timing.pixel_clock -= pixelClockRange; + high.timing.pixel_clock += pixelClockRange; + /* 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->modesNum++; + } + } + /* advance to next mode */ + src++; + } + + return B_OK; +} +/*****************************************************************************/ diff --git a/src/add-ons/kernel/drivers/graphics/et6x00/acl.c b/src/add-ons/kernel/drivers/graphics/et6x00/acl.c index cf276dab83..3f6b8053c9 100644 --- a/src/add-ons/kernel/drivers/graphics/et6x00/acl.c +++ b/src/add-ons/kernel/drivers/graphics/et6x00/acl.c @@ -1,46 +1,46 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#include "acl.h" -#include "bits.h" - - -/*****************************************************************************/ -__inline void et6000aclMasterInterruptEnable(void *base) { - set8(&((volatile char *)base)[0x34], 0x7f, 0x80); -} -/*****************************************************************************/ -__inline void et6000aclMasterInterruptDisable(void *base) { - set8(&((volatile char *)base)[0x34], 0x7f, 0x00); -} -/*****************************************************************************/ -__inline void et6000aclReadInterruptEnable(void *base) { - set8(&((volatile char *)base)[0x34], 0xfd, 0x02); -} -/*****************************************************************************/ -__inline void et6000aclReadInterruptDisable(void *base) { - set8(&((volatile char *)base)[0x34], 0xfd, 0x00); -} -/*****************************************************************************/ -__inline void et6000aclWriteInterruptEnable(void *base) { - set8(&((volatile char *)base)[0x34], 0xfe, 0x01); -} -/*****************************************************************************/ -__inline void et6000aclWriteInterruptDisable(void *base) { - set8(&((volatile char *)base)[0x34], 0xfe, 0x00); -} -/*****************************************************************************/ -__inline void et6000aclReadInterruptClear(void *base) { - set8(&((volatile char *)base)[0x35], 0xfd, 0x02); -} -/*****************************************************************************/ -__inline void et6000aclWriteInterruptClear(void *base) { - set8(&((volatile char *)base)[0x34], 0xfe, 0x00); -} -/*****************************************************************************/ -__inline char et6000aclInterruptCause(void *base) { - return ((volatile char *)base)[0x35] & 0x03; -} -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#include "acl.h" +#include "bits.h" + + +/*****************************************************************************/ +__inline void et6000aclMasterInterruptEnable(void *base) { + set8(&((volatile char *)base)[0x34], 0x7f, 0x80); +} +/*****************************************************************************/ +__inline void et6000aclMasterInterruptDisable(void *base) { + set8(&((volatile char *)base)[0x34], 0x7f, 0x00); +} +/*****************************************************************************/ +__inline void et6000aclReadInterruptEnable(void *base) { + set8(&((volatile char *)base)[0x34], 0xfd, 0x02); +} +/*****************************************************************************/ +__inline void et6000aclReadInterruptDisable(void *base) { + set8(&((volatile char *)base)[0x34], 0xfd, 0x00); +} +/*****************************************************************************/ +__inline void et6000aclWriteInterruptEnable(void *base) { + set8(&((volatile char *)base)[0x34], 0xfe, 0x01); +} +/*****************************************************************************/ +__inline void et6000aclWriteInterruptDisable(void *base) { + set8(&((volatile char *)base)[0x34], 0xfe, 0x00); +} +/*****************************************************************************/ +__inline void et6000aclReadInterruptClear(void *base) { + set8(&((volatile char *)base)[0x35], 0xfd, 0x02); +} +/*****************************************************************************/ +__inline void et6000aclWriteInterruptClear(void *base) { + set8(&((volatile char *)base)[0x34], 0xfe, 0x00); +} +/*****************************************************************************/ +__inline char et6000aclInterruptCause(void *base) { + return ((volatile char *)base)[0x35] & 0x03; +} +/*****************************************************************************/ diff --git a/src/add-ons/kernel/drivers/graphics/et6x00/acl.h b/src/add-ons/kernel/drivers/graphics/et6x00/acl.h index bed2277612..1dcfb506f8 100644 --- a/src/add-ons/kernel/drivers/graphics/et6x00/acl.h +++ b/src/add-ons/kernel/drivers/graphics/et6x00/acl.h @@ -1,27 +1,27 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ -#ifndef _ET6000ACL_H_ -#define _ET6000ACL_H_ - - -/*****************************************************************************/ -__inline void et6000aclMasterInterruptEnable(void *base); -__inline void et6000aclMasterInterruptDisable(void *base); -__inline void et6000aclReadInterruptEnable(void *base); -__inline void et6000aclReadInterruptDisable(void *base); -__inline void et6000aclWriteInterruptEnable(void *base); -__inline void et6000aclWriteInterruptDisable(void *base); -__inline void et6000aclReadInterruptClear(void *base); -__inline void et6000aclWriteInterruptClear(void *base); -__inline char et6000aclInterruptCause(void *base); -/*****************************************************************************/ -#define ET6000_ACL_INT_CAUSE_NONE 0 -#define ET6000_ACL_INT_CAUSE_READ 2 -#define ET6000_ACL_INT_CAUSE_WRITE 1 -#define ET6000_ACL_INT_CAUSE_BOTH 3 -/*****************************************************************************/ - - -#endif /* _ET6000ACL_H_ */ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ +#ifndef _ET6000ACL_H_ +#define _ET6000ACL_H_ + + +/*****************************************************************************/ +__inline void et6000aclMasterInterruptEnable(void *base); +__inline void et6000aclMasterInterruptDisable(void *base); +__inline void et6000aclReadInterruptEnable(void *base); +__inline void et6000aclReadInterruptDisable(void *base); +__inline void et6000aclWriteInterruptEnable(void *base); +__inline void et6000aclWriteInterruptDisable(void *base); +__inline void et6000aclReadInterruptClear(void *base); +__inline void et6000aclWriteInterruptClear(void *base); +__inline char et6000aclInterruptCause(void *base); +/*****************************************************************************/ +#define ET6000_ACL_INT_CAUSE_NONE 0 +#define ET6000_ACL_INT_CAUSE_READ 2 +#define ET6000_ACL_INT_CAUSE_WRITE 1 +#define ET6000_ACL_INT_CAUSE_BOTH 3 +/*****************************************************************************/ + + +#endif /* _ET6000ACL_H_ */ diff --git a/src/add-ons/kernel/drivers/graphics/et6x00/bits.c b/src/add-ons/kernel/drivers/graphics/et6x00/bits.c index c5944b8e56..cb979ee396 100644 --- a/src/add-ons/kernel/drivers/graphics/et6x00/bits.c +++ b/src/add-ons/kernel/drivers/graphics/et6x00/bits.c @@ -1,86 +1,86 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#include "bits.h" - - -/*****************************************************************************/ -/* - * Set bits in a byte pointed by addr; mask must contain 0s at the bits - * positions to be set and must contain 1s at all other bits; val must - * contain the values of bits to be set. - */ -__inline void set8(volatile char *addr, char mask, char val) -{ - if (mask == 0) - *addr = val; - else - *addr = (*addr & mask) | (val & ~mask); -} -/*****************************************************************************/ -__inline void set16(volatile short *addr, short mask, short val) -{ - if (mask == 0) - *addr = val; - else - *addr = (*addr & mask) | (val & ~mask); -} -/*****************************************************************************/ -__inline void set32(volatile int *addr, int mask, int val) -{ - if (mask == 0) - *addr = val; - else - *addr = (*addr & mask) | (val & ~mask); -} -/*****************************************************************************/ -__inline void ioSet8(short port, char mask, char val) -{ -char current; - if (mask == 0) { - __asm__ __volatile__ ( - "movb %0, %%al\n\t" - "movw %1, %%dx\n\t" - "outb %%al, %%dx" - : /* no output */ - : "r"(val), "r"(port) - : "%eax", "%edx" - ); - } - else { - __asm__ __volatile__ ( - "movw %1, %%dx;" - "inb %%dx, %%al;" - "movb %%al, %0" - : "=r"(current) - : "r"(port) - : "%eax", "%edx" - ); - current = (current & mask) | (val & ~mask); - __asm__ __volatile__ ( - "movb %0, %%al;" - "movw %1, %%dx;" - "outb %%al, %%dx" - : /* no output */ - : "r"(current), "r"(port) - : "%eax", "%edx" - ); - } -} -/*****************************************************************************/ -__inline char ioGet8(short port) -{ -char current; - __asm__ __volatile__ ( - "movw %1, %%dx;" - "inb %%dx, %%al;" - "movb %%al, %0" - : "=r"(current) - : "r"(port) - : "%eax", "%edx" - ); - return current; -} -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#include "bits.h" + + +/*****************************************************************************/ +/* + * Set bits in a byte pointed by addr; mask must contain 0s at the bits + * positions to be set and must contain 1s at all other bits; val must + * contain the values of bits to be set. + */ +__inline void set8(volatile char *addr, char mask, char val) +{ + if (mask == 0) + *addr = val; + else + *addr = (*addr & mask) | (val & ~mask); +} +/*****************************************************************************/ +__inline void set16(volatile short *addr, short mask, short val) +{ + if (mask == 0) + *addr = val; + else + *addr = (*addr & mask) | (val & ~mask); +} +/*****************************************************************************/ +__inline void set32(volatile int *addr, int mask, int val) +{ + if (mask == 0) + *addr = val; + else + *addr = (*addr & mask) | (val & ~mask); +} +/*****************************************************************************/ +__inline void ioSet8(short port, char mask, char val) +{ +char current; + if (mask == 0) { + __asm__ __volatile__ ( + "movb %0, %%al\n\t" + "movw %1, %%dx\n\t" + "outb %%al, %%dx" + : /* no output */ + : "r"(val), "r"(port) + : "%eax", "%edx" + ); + } + else { + __asm__ __volatile__ ( + "movw %1, %%dx;" + "inb %%dx, %%al;" + "movb %%al, %0" + : "=r"(current) + : "r"(port) + : "%eax", "%edx" + ); + current = (current & mask) | (val & ~mask); + __asm__ __volatile__ ( + "movb %0, %%al;" + "movw %1, %%dx;" + "outb %%al, %%dx" + : /* no output */ + : "r"(current), "r"(port) + : "%eax", "%edx" + ); + } +} +/*****************************************************************************/ +__inline char ioGet8(short port) +{ +char current; + __asm__ __volatile__ ( + "movw %1, %%dx;" + "inb %%dx, %%al;" + "movb %%al, %0" + : "=r"(current) + : "r"(port) + : "%eax", "%edx" + ); + return current; +} +/*****************************************************************************/ diff --git a/src/add-ons/kernel/drivers/graphics/et6x00/bits.h b/src/add-ons/kernel/drivers/graphics/et6x00/bits.h index 59b35bd0f9..3638391025 100644 --- a/src/add-ons/kernel/drivers/graphics/et6x00/bits.h +++ b/src/add-ons/kernel/drivers/graphics/et6x00/bits.h @@ -1,18 +1,18 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ -#ifndef _ET6000BITS_H_ -#define _ET6000BITS_H_ - - -/*****************************************************************************/ -__inline void set8(volatile char *addr, char mask, char val); -__inline void set16(volatile short *addr, short mask, short val); -__inline void set32(volatile int *addr, int mask, int val); -__inline void ioSet8(short port, char mask, char val); -__inline char ioGet8(short port); -/*****************************************************************************/ - - -#endif /* _ET6000BITS_H_ */ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ +#ifndef _ET6000BITS_H_ +#define _ET6000BITS_H_ + + +/*****************************************************************************/ +__inline void set8(volatile char *addr, char mask, char val); +__inline void set16(volatile short *addr, short mask, short val); +__inline void set32(volatile int *addr, int mask, int val); +__inline void ioSet8(short port, char mask, char val); +__inline char ioGet8(short port); +/*****************************************************************************/ + + +#endif /* _ET6000BITS_H_ */ diff --git a/src/add-ons/kernel/drivers/graphics/et6x00/driver.c b/src/add-ons/kernel/drivers/graphics/et6x00/driver.c index bf102efe1e..bf956080d7 100644 --- a/src/add-ons/kernel/drivers/graphics/et6x00/driver.c +++ b/src/add-ons/kernel/drivers/graphics/et6x00/driver.c @@ -1,713 +1,713 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -/* 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" - -#include "setmode.h" -#include "acl.h" -#include "bits.h" - -/*****************************************************************************/ -#if DEBUG > 0 -#define ddprintf(a) dprintf a -#else -#define ddprintf(a) -#endif - -#define MAX_DEVICES 8 - -/* Tell the kernel what revision of the driver API we support */ -int32 api_version = 2; - -/*****************************************************************************/ -/* This structure is private to the kernel driver */ -typedef struct { - uint32 isOpen; /* a count of how many times the devices has been opened */ - area_id sharedArea; /* the area shared between the driver and all of the accelerants */ - ET6000SharedInfo *si; /* a pointer to the shared area, for convenience */ -#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 */ -} ET6000DeviceInfo; -/*****************************************************************************/ -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 *deviceNames[MAX_DEVICES+1]; /* device name pointer storage */ - ET6000DeviceInfo di[MAX_DEVICES]; /* device specific stuff */ -} DeviceData; -/*****************************************************************************/ -static DeviceData *pd; -/*****************************************************************************/ -/* prototypes for our private functions */ -static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie); -static status_t et6000CloseHook(void* dev); -static status_t et6000FreeHook(void* dev); -static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len); -static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len); -static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len); -static status_t et6000MapDevice(ET6000DeviceInfo *di); -static void et6000UnmapDevice(ET6000DeviceInfo *di); -static void et6000ProbeDevices(void); -static int32 et6000Interrupt(void *data); - -#if DEBUG > 0 -static int et6000dump(int argc, char **argv); -#endif -/*****************************************************************************/ -static pci_module_info *pci_bus; - -#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)) -/*****************************************************************************/ -static device_hooks et6000DeviceHooks = { - et6000OpenHook, - et6000CloseHook, - et6000FreeHook, - et6000ControlHook, - et6000ReadHook, - et6000WriteHook, - NULL, - NULL, - NULL, - NULL -}; -/*****************************************************************************/ -#define TSENG_VENDOR_ID 0x100C /* Tseng Labs Inc */ - -static uint16 et6000DeviceList[] = { - 0x3208, /* ET6000/ET6100 */ - 0x4702, /* ET6300 */ - 0 -}; - -static struct { - uint16 vendor; - uint16 *devices; -} supportedDevices[] = { - {TSENG_VENDOR_ID, et6000DeviceList}, - {0x0000, NULL} -}; -/*****************************************************************************/ -/* - * Returns B_OK if one is found, otherwise returns - * B_ERROR so the driver will be unloaded. - */ -status_t init_hardware(void) { -long pciIndex = 0; -pci_info pcii; -bool foundOne = 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)(pciIndex, &pcii) == B_NO_ERROR) { - int vendor = 0; - - ddprintf(("ET6000 init_hardware(): checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, 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(("ET6000: we support this device\n")); - foundOne = TRUE; - goto done; - } - /* next supported device */ - devices++; - } - } - vendor++; - } - /* next pci_info struct, please */ - pciIndex++; - } - ddprintf(("ET6000: init_hardware - no supported devices\n")); - -done: - /* put away the module manager */ - put_module(B_PCI_MODULE_NAME); - return (foundOne ? B_OK : B_ERROR); -} -/*****************************************************************************/ -static void et6000ProbeDevices(void) { -uint32 pciIndex = 0; -uint32 count = 0; -ET6000DeviceInfo *di = pd->di; - - /* while there are more pci devices */ - while ((count < MAX_DEVICES) && - ((*pci_bus->get_nth_pci_info)(pciIndex, &(di->pcii)) == B_NO_ERROR)) - { - int vendor = 0; - - ddprintf(("ET6000: checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, di->pcii.vendor_id, di->pcii.device_id)); - /* 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(("ET6000: making /dev/%s\n", di->name)); - /* remember the name */ - pd->deviceNames[count] = di->name; - /* mark the driver as available for R/W open */ - di->isOpen = 0; - /* mark areas as not yet created */ - di->sharedArea = -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 */ - pciIndex++; - } - /* propagate count */ - pd->count = count; - /* terminate list of device names with a null pointer */ - pd->deviceNames[pd->count] = NULL; - ddprintf(("SKD et6000ProbeDevices: %ld supported devices\n", pd->count)); -} -/*****************************************************************************/ -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 */ - et6000ProbeDevices(); - -#if DEBUG > 0 - add_debugger_command("et6000dump", et6000dump, "dump ET6000 kernel driver persistant data"); -#endif - - return B_OK; -} -/*****************************************************************************/ -const char **publish_devices(void) { - /* return the list of supported devices */ - return (const char **)pd->deviceNames; -} -/*****************************************************************************/ -device_hooks *find_device(const char *name) { -int index = 0; - while (pd->deviceNames[index]) { - if (strcmp(name, pd->deviceNames[index]) == 0) - return &et6000DeviceHooks; - index++; - } - return NULL; -} -/*****************************************************************************/ -void uninit_driver(void) { - -#if DEBUG > 0 - remove_debugger_command("et6000dump", et6000dump); -#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 int32 et6000Interrupt(void *data) { -int32 handled = B_UNHANDLED_INTERRUPT; -ET6000DeviceInfo *di = (ET6000DeviceInfo *)data; -ET6000SharedInfo *si = di->si; -int32 *flags = &(si->flags); - -#if DEBUG > 0 - pd->total_interrupts++; -#endif - - /* is someone already handling an interrupt for this device? */ - if (atomic_or(flags, ET6000_HANDLER_INSTALLED) & ET6000_HANDLER_INSTALLED) { -#if DEBUG > 0 - kprintf("ET6000: Already in handler!\n"); -#endif - goto exit0; - } - - switch (et6000aclInterruptCause(si->mmRegs)) { - case ET6000_ACL_INT_CAUSE_NONE: - handled = B_UNHANDLED_INTERRUPT; - break; - case ET6000_ACL_INT_CAUSE_READ: - et6000aclReadInterruptClear(si->mmRegs); - handled = B_HANDLED_INTERRUPT; - break; - case ET6000_ACL_INT_CAUSE_WRITE: - et6000aclWriteInterruptClear(si->mmRegs); - handled = B_HANDLED_INTERRUPT; - break; - case ET6000_ACL_INT_CAUSE_BOTH: /* Can it be at all? */ - et6000aclReadInterruptClear(si->mmRegs); - et6000aclWriteInterruptClear(si->mmRegs); - handled = B_HANDLED_INTERRUPT; - break; - } - -#if DEBUG > 0 - /* increment the counter for this device */ - if (handled == B_HANDLED_INTERRUPT) - di->interrupt_count++; -#endif - - /* note that we're not in the handler any more */ - atomic_and(flags, ~ET6000_HANDLER_INSTALLED); - -exit0: - return handled; -} -/*****************************************************************************/ -uint32 et6000GetOnboardMemorySize(uint16 pciConfigSpace, - volatile void *memory) -{ -uint32 memSize = 0; - - ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */ - ioSet8(0x3b8, 0x00, 0xa0); /* Set the KEY for monochrome modes */ - - switch (ioGet8(0x3C2) & 0x03) { - case 0x00: /* onboard memory is of DRAM type */ - memSize = 1024*1024 * ((ioGet8(pciConfigSpace + 0x45) & 0x03) + 1); - break; - case 0x03: /* onboard memory is of MDRAM type */ - memSize = /* number*8 of 32kb banks per channel */ - ((ioGet8(pciConfigSpace + 0x47) & 0x07) + 1) * 8 * 32*1024; - if (ioGet8(pciConfigSpace + 0x45) & 0x04) /* If 2 channels */ - memSize *= 2; - break; - default: /* onboard memory is of unknown type */ - memSize = 4196*1024; /* Let it be of maximum possible size */ - } - - /* - * This algorithm would fail to recongize 2.25Mb of onboard - * memory - it would detect 2.5Mb instead. It needs to be fixed. - */ - if (memSize == 2621440) { /* If 2.5Mb detected */ - uint8 pci40 = ioGet8(pciConfigSpace+0x40); - et6000EnableLinearMemoryMapping(pciConfigSpace); - - /* Check whether the memory beyond 2.25Mb really exists */ - *(volatile uint32 *)((uint32)memory + 2359296) = 0xaa55aa55; - if (*(volatile uint32 *)((uint32)memory + 2359296) != 0xaa55aa55) - memSize = 2359296; /* It's 2.25Mb */ - - ioSet8(pciConfigSpace+0x40, 0x00, pci40); /* Restore */ - } - - return memSize; -} -/*****************************************************************************/ -static status_t et6000MapDevice(ET6000DeviceInfo *di) { -char buffer[B_OS_NAME_LENGTH]; -ET6000SharedInfo *si = di->si; -uint32 tmpUlong; -pci_info *pcii = &(di->pcii); - - /* Enable memory space access and I/O space access */ - tmpUlong = get_pci(PCI_command, 4); - tmpUlong |= 0x00000003; - set_pci(PCI_command, 4, tmpUlong); - - /* Enable ROM decoding */ - tmpUlong = get_pci(PCI_rom_base, 4); - tmpUlong |= 0x00000001; - set_pci(PCI_rom_base, 4, tmpUlong); - - /* PCI header base address in I/O space */ - si->pciConfigSpace = (uint16)di->pcii.u.h0.base_registers[1]; - - sprintf(buffer, "%04X_%04X_%02X%02X%02X videomemory", - di->pcii.vendor_id, di->pcii.device_id, - di->pcii.bus, di->pcii.device, di->pcii.function); - - /* - * We map the whole graphics card memory area (which consist of RAM memory - * and memory mapped registers) at once. Memory mapped registers must not - * be cacheble, so the whole area is mapped with B_MTR_UC (unable caching). - * We certainly could map separately the RAM memory with write combining - * (B_MTR_WC) and the memory mapped registers with B_MTR_UC. - */ - si->memoryArea = map_physical_memory(buffer, - (void *)di->pcii.u.h0.base_registers[0], - di->pcii.u.h0.base_register_sizes[0], - B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_UC, - B_READ_AREA + B_WRITE_AREA, - &(si->memory)); - - si->framebuffer = si->memory; - si->mmRegs = (void *)((uint32)si->memory + 0x003fff00); - si->emRegs = (void *)((uint32)si->memory + 0x003fe000); - - /* remember the physical addresses */ - si->physMemory = si->physFramebuffer = - (void *) di->pcii.u.h0.base_registers_pci[0]; - - si->memSize = et6000GetOnboardMemorySize(si->pciConfigSpace, si->memory); - - /* in any case, return the result */ - return si->memoryArea; -} -/*****************************************************************************/ -static void et6000UnmapDevice(ET6000DeviceInfo *di) { -ET6000SharedInfo *si = di->si; - - ddprintf(("et6000UnmapDevice(%08lx) begins...\n", (uint32)di)); - ddprintf((" memoryArea: %ld\n", si->memoryArea)); - - if (si->memoryArea >= 0) - delete_area(si->memoryArea); - si->memoryArea = -1; - si->framebuffer = NULL; - si->physFramebuffer = NULL; - si->memory = NULL; - si->physMemory = NULL; - - ddprintf(("et6000UnmapDevice() ends.\n")); -} -/*****************************************************************************/ -static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie) { -int32 index = 0; -ET6000DeviceInfo *di; -ET6000SharedInfo *si; -status_t result = B_OK; -char shared_name[B_OS_NAME_LENGTH]; - - ddprintf(("SKD et6000OpenHook(%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->deviceNames[index] && - (strcmp(name, pd->deviceNames[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->isOpen) { - /* 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->sharedArea = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(ET6000SharedInfo) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 0); - if (di->sharedArea < 0) { - /* return the error */ - result = di->sharedArea; - 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; - - si->pixelClockMax16 = 135000; - si->pixelClockMax24 = 135000; - if (si->vendor_id == 0x100C) { /* Tseng Labs, Inc. */ - switch (si->device_id) { - case 0x3208:/* ET6000/ET6100 */ - if (si->revision < 0x70) { /* ET6000 */ - si->pixelClockMax16 = 135000; - si->pixelClockMax24 = 135000; - } - else { /* ET6100 */ - si->pixelClockMax16 = 175000; - si->pixelClockMax24 = 175000; - } - break; - case 0x4702: /* ET6300 */ - si->pixelClockMax16 = 220000; - si->pixelClockMax24 = 220000; - break; - } - } - - /* map the device */ - result = et6000MapDevice(di); - if (result < 0) - goto free_shared; - result = B_OK; - - /* - * Clear any pending interrupts and disable interrupts. Driver - * currently does not use interrupts and unlikely will in future. - */ - et6000aclReadInterruptClear(si->mmRegs); - et6000aclWriteInterruptClear(si->mmRegs); - et6000aclMasterInterruptDisable(si->mmRegs); - - /* Install the interrupt handler */ - result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, - et6000Interrupt, (void *)di, 0); - /* bail if we couldn't install the handler */ - if (result != B_OK) - goto unmap; - -mark_as_open: - /* mark the device open */ - di->isOpen++; - - /* send the cookie to the opener */ - *cookie = di; - - goto done; - -unmap: - et6000UnmapDevice(di); - -free_shared: - /* clean up our shared area */ - delete_area(di->sharedArea); - di->sharedArea = -1; - di->si = NULL; - -done: - /* end of critical section */ - RELEASE_BEN(pd->kernel); - - /* all done, return the status */ - ddprintf(("et6000OpenHook returning 0x%08lx\n", result)); - - return result; -} -/*****************************************************************************/ -/* - * et6000ReadHook - does nothing, gracefully - */ -static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len) -{ - *len = 0; - return B_NOT_ALLOWED; -} - -/*****************************************************************************/ -/* - * et6000WriteHook - does nothing, gracefully - */ -static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len) -{ - *len = 0; - return B_NOT_ALLOWED; -} -/*****************************************************************************/ -/* - * et6000CloseHook - does nothing, gracefully - */ -static status_t et6000CloseHook(void* dev) -{ - ddprintf(("SKD et6000CloseHook(%08lx)\n", (uint32)dev)); - /* we don't do anything on close: there might be dup'd fd */ - return B_NO_ERROR; -} -/*****************************************************************************/ -/* - * et6000FreeHook - close down the device - */ -static status_t et6000FreeHook(void* dev) { -ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev; -ET6000SharedInfo *si = di->si; - - ddprintf(("SKD et6000FreeHook() begins...\n")); - /* lock the driver */ - AQUIRE_BEN(pd->kernel); - - /* if opened multiple times, decrement the open count and exit */ - if (di->isOpen > 1) - goto unlock_and_exit; - - /* Clear any pending interrupts and disable interrupts. */ - et6000aclReadInterruptClear(si->mmRegs); - et6000aclWriteInterruptClear(si->mmRegs); - et6000aclMasterInterruptDisable(si->mmRegs); - - /* Remove the interrupt handler */ - remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, et6000Interrupt, di); - - /* free framebuffer area */ - et6000UnmapDevice(di); - - /* clean up our shared area */ - delete_area(di->sharedArea); - di->sharedArea = -1; - di->si = NULL; - -unlock_and_exit: - /* mark the device available */ - di->isOpen--; - /* unlock the driver */ - RELEASE_BEN(pd->kernel); - ddprintf(("SKD et6000FreeHook() ends.\n")); - /* all done */ - return B_OK; -} -/*****************************************************************************/ -/* - * et6000ControlHook - where the real work is done - */ -static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len) { -ET6000DeviceInfo *di = (ET6000DeviceInfo *)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, "et6000.accelerant"); - result = B_OK; - } break; - - /* PRIVATE ioctl from here on */ - case ET6000_GET_PRIVATE_DATA: { - ET6000GetPrivateData *gpd = (ET6000GetPrivateData *)buf; - if (gpd->magic == ET6000_PRIVATE_DATA_MAGIC) { - gpd->sharedInfoArea = di->sharedArea; - result = B_OK; - } - } break; - - case ET6000_GET_PCI: { - ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf; - if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) { - pci_info *pcii = &(di->pcii); - gsp->value = get_pci(gsp->offset, gsp->size); - result = B_OK; - } - } break; - - case ET6000_SET_PCI: { - ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf; - if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) { - pci_info *pcii = &(di->pcii); - set_pci(gsp->offset, gsp->size, gsp->value); - result = B_OK; - } - } break; - - case ET6000_DEVICE_NAME: { /* Needed for cloning */ - ET6000DeviceName *dn = (ET6000DeviceName *)buf; - if(dn->magic == ET6000_PRIVATE_DATA_MAGIC) { - strncpy(dn->name, di->name, B_OS_NAME_LENGTH); - result = B_OK; - } - } break; - - case ET6000_PROPOSE_DISPLAY_MODE: { - ET6000DisplayMode *dm = (ET6000DisplayMode *)buf; - if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) { - result = et6000ProposeMode(&dm->mode, dm->memSize); - } - } break; - - case ET6000_SET_DISPLAY_MODE: { - ET6000DisplayMode *dm = (ET6000DisplayMode *)buf; - if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) { - result = et6000SetMode(&dm->mode, dm->pciConfigSpace); - } - } break; - } - return result; -} -/*****************************************************************************/ -#if DEBUG > 0 -static int et6000dump(int argc, char **argv) { -int i; - - kprintf("ET6000 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++) { - ET6000DeviceInfo *di = &(pd->di[i]); - uint16 device_id = di->pcii.device_id; - ET6000SharedInfo *si = di->si; - kprintf(" device_id: 0x%04x\n", device_id); - kprintf(" interrupt count: %ld\n", di->interrupt_count); - if (si) { - kprintf(" flags:"); - } - kprintf("\n"); - } - return 1; /* the magic number for success */ -} -#endif -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +/* 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" + +#include "setmode.h" +#include "acl.h" +#include "bits.h" + +/*****************************************************************************/ +#if DEBUG > 0 +#define ddprintf(a) dprintf a +#else +#define ddprintf(a) +#endif + +#define MAX_DEVICES 8 + +/* Tell the kernel what revision of the driver API we support */ +int32 api_version = 2; + +/*****************************************************************************/ +/* This structure is private to the kernel driver */ +typedef struct { + uint32 isOpen; /* a count of how many times the devices has been opened */ + area_id sharedArea; /* the area shared between the driver and all of the accelerants */ + ET6000SharedInfo *si; /* a pointer to the shared area, for convenience */ +#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 */ +} ET6000DeviceInfo; +/*****************************************************************************/ +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 *deviceNames[MAX_DEVICES+1]; /* device name pointer storage */ + ET6000DeviceInfo di[MAX_DEVICES]; /* device specific stuff */ +} DeviceData; +/*****************************************************************************/ +static DeviceData *pd; +/*****************************************************************************/ +/* prototypes for our private functions */ +static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie); +static status_t et6000CloseHook(void* dev); +static status_t et6000FreeHook(void* dev); +static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len); +static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len); +static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len); +static status_t et6000MapDevice(ET6000DeviceInfo *di); +static void et6000UnmapDevice(ET6000DeviceInfo *di); +static void et6000ProbeDevices(void); +static int32 et6000Interrupt(void *data); + +#if DEBUG > 0 +static int et6000dump(int argc, char **argv); +#endif +/*****************************************************************************/ +static pci_module_info *pci_bus; + +#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)) +/*****************************************************************************/ +static device_hooks et6000DeviceHooks = { + et6000OpenHook, + et6000CloseHook, + et6000FreeHook, + et6000ControlHook, + et6000ReadHook, + et6000WriteHook, + NULL, + NULL, + NULL, + NULL +}; +/*****************************************************************************/ +#define TSENG_VENDOR_ID 0x100C /* Tseng Labs Inc */ + +static uint16 et6000DeviceList[] = { + 0x3208, /* ET6000/ET6100 */ + 0x4702, /* ET6300 */ + 0 +}; + +static struct { + uint16 vendor; + uint16 *devices; +} supportedDevices[] = { + {TSENG_VENDOR_ID, et6000DeviceList}, + {0x0000, NULL} +}; +/*****************************************************************************/ +/* + * Returns B_OK if one is found, otherwise returns + * B_ERROR so the driver will be unloaded. + */ +status_t init_hardware(void) { +long pciIndex = 0; +pci_info pcii; +bool foundOne = 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)(pciIndex, &pcii) == B_NO_ERROR) { + int vendor = 0; + + ddprintf(("ET6000 init_hardware(): checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, 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(("ET6000: we support this device\n")); + foundOne = TRUE; + goto done; + } + /* next supported device */ + devices++; + } + } + vendor++; + } + /* next pci_info struct, please */ + pciIndex++; + } + ddprintf(("ET6000: init_hardware - no supported devices\n")); + +done: + /* put away the module manager */ + put_module(B_PCI_MODULE_NAME); + return (foundOne ? B_OK : B_ERROR); +} +/*****************************************************************************/ +static void et6000ProbeDevices(void) { +uint32 pciIndex = 0; +uint32 count = 0; +ET6000DeviceInfo *di = pd->di; + + /* while there are more pci devices */ + while ((count < MAX_DEVICES) && + ((*pci_bus->get_nth_pci_info)(pciIndex, &(di->pcii)) == B_NO_ERROR)) + { + int vendor = 0; + + ddprintf(("ET6000: checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, di->pcii.vendor_id, di->pcii.device_id)); + /* 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(("ET6000: making /dev/%s\n", di->name)); + /* remember the name */ + pd->deviceNames[count] = di->name; + /* mark the driver as available for R/W open */ + di->isOpen = 0; + /* mark areas as not yet created */ + di->sharedArea = -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 */ + pciIndex++; + } + /* propagate count */ + pd->count = count; + /* terminate list of device names with a null pointer */ + pd->deviceNames[pd->count] = NULL; + ddprintf(("SKD et6000ProbeDevices: %ld supported devices\n", pd->count)); +} +/*****************************************************************************/ +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 */ + et6000ProbeDevices(); + +#if DEBUG > 0 + add_debugger_command("et6000dump", et6000dump, "dump ET6000 kernel driver persistant data"); +#endif + + return B_OK; +} +/*****************************************************************************/ +const char **publish_devices(void) { + /* return the list of supported devices */ + return (const char **)pd->deviceNames; +} +/*****************************************************************************/ +device_hooks *find_device(const char *name) { +int index = 0; + while (pd->deviceNames[index]) { + if (strcmp(name, pd->deviceNames[index]) == 0) + return &et6000DeviceHooks; + index++; + } + return NULL; +} +/*****************************************************************************/ +void uninit_driver(void) { + +#if DEBUG > 0 + remove_debugger_command("et6000dump", et6000dump); +#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 int32 et6000Interrupt(void *data) { +int32 handled = B_UNHANDLED_INTERRUPT; +ET6000DeviceInfo *di = (ET6000DeviceInfo *)data; +ET6000SharedInfo *si = di->si; +int32 *flags = &(si->flags); + +#if DEBUG > 0 + pd->total_interrupts++; +#endif + + /* is someone already handling an interrupt for this device? */ + if (atomic_or(flags, ET6000_HANDLER_INSTALLED) & ET6000_HANDLER_INSTALLED) { +#if DEBUG > 0 + kprintf("ET6000: Already in handler!\n"); +#endif + goto exit0; + } + + switch (et6000aclInterruptCause(si->mmRegs)) { + case ET6000_ACL_INT_CAUSE_NONE: + handled = B_UNHANDLED_INTERRUPT; + break; + case ET6000_ACL_INT_CAUSE_READ: + et6000aclReadInterruptClear(si->mmRegs); + handled = B_HANDLED_INTERRUPT; + break; + case ET6000_ACL_INT_CAUSE_WRITE: + et6000aclWriteInterruptClear(si->mmRegs); + handled = B_HANDLED_INTERRUPT; + break; + case ET6000_ACL_INT_CAUSE_BOTH: /* Can it be at all? */ + et6000aclReadInterruptClear(si->mmRegs); + et6000aclWriteInterruptClear(si->mmRegs); + handled = B_HANDLED_INTERRUPT; + break; + } + +#if DEBUG > 0 + /* increment the counter for this device */ + if (handled == B_HANDLED_INTERRUPT) + di->interrupt_count++; +#endif + + /* note that we're not in the handler any more */ + atomic_and(flags, ~ET6000_HANDLER_INSTALLED); + +exit0: + return handled; +} +/*****************************************************************************/ +uint32 et6000GetOnboardMemorySize(uint16 pciConfigSpace, + volatile void *memory) +{ +uint32 memSize = 0; + + ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */ + ioSet8(0x3b8, 0x00, 0xa0); /* Set the KEY for monochrome modes */ + + switch (ioGet8(0x3C2) & 0x03) { + case 0x00: /* onboard memory is of DRAM type */ + memSize = 1024*1024 * ((ioGet8(pciConfigSpace + 0x45) & 0x03) + 1); + break; + case 0x03: /* onboard memory is of MDRAM type */ + memSize = /* number*8 of 32kb banks per channel */ + ((ioGet8(pciConfigSpace + 0x47) & 0x07) + 1) * 8 * 32*1024; + if (ioGet8(pciConfigSpace + 0x45) & 0x04) /* If 2 channels */ + memSize *= 2; + break; + default: /* onboard memory is of unknown type */ + memSize = 4196*1024; /* Let it be of maximum possible size */ + } + + /* + * This algorithm would fail to recongize 2.25Mb of onboard + * memory - it would detect 2.5Mb instead. It needs to be fixed. + */ + if (memSize == 2621440) { /* If 2.5Mb detected */ + uint8 pci40 = ioGet8(pciConfigSpace+0x40); + et6000EnableLinearMemoryMapping(pciConfigSpace); + + /* Check whether the memory beyond 2.25Mb really exists */ + *(volatile uint32 *)((uint32)memory + 2359296) = 0xaa55aa55; + if (*(volatile uint32 *)((uint32)memory + 2359296) != 0xaa55aa55) + memSize = 2359296; /* It's 2.25Mb */ + + ioSet8(pciConfigSpace+0x40, 0x00, pci40); /* Restore */ + } + + return memSize; +} +/*****************************************************************************/ +static status_t et6000MapDevice(ET6000DeviceInfo *di) { +char buffer[B_OS_NAME_LENGTH]; +ET6000SharedInfo *si = di->si; +uint32 tmpUlong; +pci_info *pcii = &(di->pcii); + + /* Enable memory space access and I/O space access */ + tmpUlong = get_pci(PCI_command, 4); + tmpUlong |= 0x00000003; + set_pci(PCI_command, 4, tmpUlong); + + /* Enable ROM decoding */ + tmpUlong = get_pci(PCI_rom_base, 4); + tmpUlong |= 0x00000001; + set_pci(PCI_rom_base, 4, tmpUlong); + + /* PCI header base address in I/O space */ + si->pciConfigSpace = (uint16)di->pcii.u.h0.base_registers[1]; + + sprintf(buffer, "%04X_%04X_%02X%02X%02X videomemory", + di->pcii.vendor_id, di->pcii.device_id, + di->pcii.bus, di->pcii.device, di->pcii.function); + + /* + * We map the whole graphics card memory area (which consist of RAM memory + * and memory mapped registers) at once. Memory mapped registers must not + * be cacheble, so the whole area is mapped with B_MTR_UC (unable caching). + * We certainly could map separately the RAM memory with write combining + * (B_MTR_WC) and the memory mapped registers with B_MTR_UC. + */ + si->memoryArea = map_physical_memory(buffer, + (void *)di->pcii.u.h0.base_registers[0], + di->pcii.u.h0.base_register_sizes[0], + B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_UC, + B_READ_AREA + B_WRITE_AREA, + &(si->memory)); + + si->framebuffer = si->memory; + si->mmRegs = (void *)((uint32)si->memory + 0x003fff00); + si->emRegs = (void *)((uint32)si->memory + 0x003fe000); + + /* remember the physical addresses */ + si->physMemory = si->physFramebuffer = + (void *) di->pcii.u.h0.base_registers_pci[0]; + + si->memSize = et6000GetOnboardMemorySize(si->pciConfigSpace, si->memory); + + /* in any case, return the result */ + return si->memoryArea; +} +/*****************************************************************************/ +static void et6000UnmapDevice(ET6000DeviceInfo *di) { +ET6000SharedInfo *si = di->si; + + ddprintf(("et6000UnmapDevice(%08lx) begins...\n", (uint32)di)); + ddprintf((" memoryArea: %ld\n", si->memoryArea)); + + if (si->memoryArea >= 0) + delete_area(si->memoryArea); + si->memoryArea = -1; + si->framebuffer = NULL; + si->physFramebuffer = NULL; + si->memory = NULL; + si->physMemory = NULL; + + ddprintf(("et6000UnmapDevice() ends.\n")); +} +/*****************************************************************************/ +static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie) { +int32 index = 0; +ET6000DeviceInfo *di; +ET6000SharedInfo *si; +status_t result = B_OK; +char shared_name[B_OS_NAME_LENGTH]; + + ddprintf(("SKD et6000OpenHook(%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->deviceNames[index] && + (strcmp(name, pd->deviceNames[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->isOpen) { + /* 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->sharedArea = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(ET6000SharedInfo) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 0); + if (di->sharedArea < 0) { + /* return the error */ + result = di->sharedArea; + 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; + + si->pixelClockMax16 = 135000; + si->pixelClockMax24 = 135000; + if (si->vendor_id == 0x100C) { /* Tseng Labs, Inc. */ + switch (si->device_id) { + case 0x3208:/* ET6000/ET6100 */ + if (si->revision < 0x70) { /* ET6000 */ + si->pixelClockMax16 = 135000; + si->pixelClockMax24 = 135000; + } + else { /* ET6100 */ + si->pixelClockMax16 = 175000; + si->pixelClockMax24 = 175000; + } + break; + case 0x4702: /* ET6300 */ + si->pixelClockMax16 = 220000; + si->pixelClockMax24 = 220000; + break; + } + } + + /* map the device */ + result = et6000MapDevice(di); + if (result < 0) + goto free_shared; + result = B_OK; + + /* + * Clear any pending interrupts and disable interrupts. Driver + * currently does not use interrupts and unlikely will in future. + */ + et6000aclReadInterruptClear(si->mmRegs); + et6000aclWriteInterruptClear(si->mmRegs); + et6000aclMasterInterruptDisable(si->mmRegs); + + /* Install the interrupt handler */ + result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, + et6000Interrupt, (void *)di, 0); + /* bail if we couldn't install the handler */ + if (result != B_OK) + goto unmap; + +mark_as_open: + /* mark the device open */ + di->isOpen++; + + /* send the cookie to the opener */ + *cookie = di; + + goto done; + +unmap: + et6000UnmapDevice(di); + +free_shared: + /* clean up our shared area */ + delete_area(di->sharedArea); + di->sharedArea = -1; + di->si = NULL; + +done: + /* end of critical section */ + RELEASE_BEN(pd->kernel); + + /* all done, return the status */ + ddprintf(("et6000OpenHook returning 0x%08lx\n", result)); + + return result; +} +/*****************************************************************************/ +/* + * et6000ReadHook - does nothing, gracefully + */ +static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len) +{ + *len = 0; + return B_NOT_ALLOWED; +} + +/*****************************************************************************/ +/* + * et6000WriteHook - does nothing, gracefully + */ +static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len) +{ + *len = 0; + return B_NOT_ALLOWED; +} +/*****************************************************************************/ +/* + * et6000CloseHook - does nothing, gracefully + */ +static status_t et6000CloseHook(void* dev) +{ + ddprintf(("SKD et6000CloseHook(%08lx)\n", (uint32)dev)); + /* we don't do anything on close: there might be dup'd fd */ + return B_NO_ERROR; +} +/*****************************************************************************/ +/* + * et6000FreeHook - close down the device + */ +static status_t et6000FreeHook(void* dev) { +ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev; +ET6000SharedInfo *si = di->si; + + ddprintf(("SKD et6000FreeHook() begins...\n")); + /* lock the driver */ + AQUIRE_BEN(pd->kernel); + + /* if opened multiple times, decrement the open count and exit */ + if (di->isOpen > 1) + goto unlock_and_exit; + + /* Clear any pending interrupts and disable interrupts. */ + et6000aclReadInterruptClear(si->mmRegs); + et6000aclWriteInterruptClear(si->mmRegs); + et6000aclMasterInterruptDisable(si->mmRegs); + + /* Remove the interrupt handler */ + remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, et6000Interrupt, di); + + /* free framebuffer area */ + et6000UnmapDevice(di); + + /* clean up our shared area */ + delete_area(di->sharedArea); + di->sharedArea = -1; + di->si = NULL; + +unlock_and_exit: + /* mark the device available */ + di->isOpen--; + /* unlock the driver */ + RELEASE_BEN(pd->kernel); + ddprintf(("SKD et6000FreeHook() ends.\n")); + /* all done */ + return B_OK; +} +/*****************************************************************************/ +/* + * et6000ControlHook - where the real work is done + */ +static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len) { +ET6000DeviceInfo *di = (ET6000DeviceInfo *)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, "et6000.accelerant"); + result = B_OK; + } break; + + /* PRIVATE ioctl from here on */ + case ET6000_GET_PRIVATE_DATA: { + ET6000GetPrivateData *gpd = (ET6000GetPrivateData *)buf; + if (gpd->magic == ET6000_PRIVATE_DATA_MAGIC) { + gpd->sharedInfoArea = di->sharedArea; + result = B_OK; + } + } break; + + case ET6000_GET_PCI: { + ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf; + if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) { + pci_info *pcii = &(di->pcii); + gsp->value = get_pci(gsp->offset, gsp->size); + result = B_OK; + } + } break; + + case ET6000_SET_PCI: { + ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf; + if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) { + pci_info *pcii = &(di->pcii); + set_pci(gsp->offset, gsp->size, gsp->value); + result = B_OK; + } + } break; + + case ET6000_DEVICE_NAME: { /* Needed for cloning */ + ET6000DeviceName *dn = (ET6000DeviceName *)buf; + if(dn->magic == ET6000_PRIVATE_DATA_MAGIC) { + strncpy(dn->name, di->name, B_OS_NAME_LENGTH); + result = B_OK; + } + } break; + + case ET6000_PROPOSE_DISPLAY_MODE: { + ET6000DisplayMode *dm = (ET6000DisplayMode *)buf; + if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) { + result = et6000ProposeMode(&dm->mode, dm->memSize); + } + } break; + + case ET6000_SET_DISPLAY_MODE: { + ET6000DisplayMode *dm = (ET6000DisplayMode *)buf; + if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) { + result = et6000SetMode(&dm->mode, dm->pciConfigSpace); + } + } break; + } + return result; +} +/*****************************************************************************/ +#if DEBUG > 0 +static int et6000dump(int argc, char **argv) { +int i; + + kprintf("ET6000 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++) { + ET6000DeviceInfo *di = &(pd->di[i]); + uint16 device_id = di->pcii.device_id; + ET6000SharedInfo *si = di->si; + kprintf(" device_id: 0x%04x\n", device_id); + kprintf(" interrupt count: %ld\n", di->interrupt_count); + if (si) { + kprintf(" flags:"); + } + kprintf("\n"); + } + return 1; /* the magic number for success */ +} +#endif +/*****************************************************************************/ diff --git a/src/add-ons/kernel/drivers/graphics/et6x00/setmode.c b/src/add-ons/kernel/drivers/graphics/et6x00/setmode.c index 3a9b70c2e6..d8647bb5c0 100644 --- a/src/add-ons/kernel/drivers/graphics/et6x00/setmode.c +++ b/src/add-ons/kernel/drivers/graphics/et6x00/setmode.c @@ -1,430 +1,430 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ - -#include "setmode.h" - - -/* - * ATTENTION: Currently we set the graphics modes by setting the registers - * with the beforehand dumped values of the corresponding registers. So not - * all graphics modes ET6x00 chips are capable of are accessible. So it would - * be great to implement the normal algorithm of run-time computing of the - * values to set the register. - */ - - -/*****************************************************************************/ -typedef struct { - uint32 VisScreenWidth; - uint32 VisScreenHeight; - uint8 BitsPerPlane; - uint8 NumberGreenBits; - uint16 Frequency; -} VIDEO_MODE_INFORMATION; -/*****************************************************************************/ -/* - * ATTENTION: Don't forget that CRTC indexed register 0x11 - * bit[7] write-protects some registers. - */ -struct { - uint16 width, height, bpp, refreshRate; - uint8 clock0M, clock0N; - uint8 pci42; /* contains MCLK divider (MDIV) */ - uint8 crtc[64]; -} clock0MN[] = { - {640, 480, 24, 75, 0x28, 0x22, 0x02, - {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - {640, 480, 24, 72, 0x56, 0x63, 0x00, - {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe8, 0x0b, 0xdf, 0xf0, 0x60, 0xe7, 0xff, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - {640, 480, 24, 60, 0x28, 0x22, 0x02, - {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - - {640, 480, 16, 75, 0x56, 0x43, 0x01, - {0x64, 0x4f, 0x4f, 0x88, 0x54, 0x9c, 0xf2, 0x1f, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0x03, 0xdf, 0xa0, 0x60, 0xdf, 0xf3, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - {640, 480, 16, 72, 0x56, 0x43, 0x01, - {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe8, 0x0b, 0xdf, 0xa0, 0x60, 0xe7, 0xff, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - {640, 480, 16, 60, 0x28, 0x41, 0x01, - {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xea, 0x0c, 0xdf, 0xa0, 0x60, 0xe7, 0x04, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - - {800, 600, 24, 75, 0x79, 0x49, 0x00, - {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, - {800, 600, 24, 72, 0x28, 0x41, 0x00, - {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x02, 0x57, 0x2c, 0x60, 0x57, 0x99, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, - {800, 600, 24, 60, 0x79, 0x49, 0x00, - {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, - - {800, 600, 16, 75, 0x51, 0x44, 0x00, - {0x7f, 0x63, 0x63, 0x83, 0x68, 0x12, 0x6f, 0xf0, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x0b, 0x57, 0xc8, 0x60, 0x57, 0x70, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - {800, 600, 16, 72, 0x28, 0x41, 0x00, - {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x02, 0x57, 0xc8, 0x60, 0x57, 0x99, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - {800, 600, 16, 60, 0x79, 0x49, 0x00, - {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x0c, 0x57, 0xc8, 0x60, 0x57, 0x73, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, - - {1024, 768, 16, 75, 0x1f, 0x21, 0x00, - {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, - {1024, 768, 16, 70, 0x28, 0x22, 0x00, - {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, - {1024, 768, 16, 60, 0x6b, 0x44, 0x00, - {0xa1, 0x7f, 0x80, 0x84, 0x88, 0x99, 0x26, 0xfd, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x0a, 0xff, 0x00, 0x60, 0x04, 0x22, 0xab, - 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, -}; - -#define CLOCK0MN (sizeof(clock0MN) / sizeof(clock0MN[0])) -/*****************************************************************************/ -__inline void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace) -{ - /* - * Relocate memory via PCI Base Address 0; don't enable MMU; - * enable memory mapped registers; enable system linear memory mapping. - */ - ioSet8(pciConfigSpace+0x40, 0xf0, 0x0b); -} -/*****************************************************************************/ -static void setPCIConfigSpaceRegisters41to5E(uint16 pciConfigSpace, - VIDEO_MODE_INFORMATION *mi, - uint32 m) -{ -uint8 pci415e[30] = { - 0x3a, 0x00, 0x02, 0x15, 0x04, 0x40, 0x13, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}; -uint8 i; - - pci415e[1] = clock0MN[m].pci42; - - for (i=0x41; i<0x5f; i++) { - if ((i==0x45) || ((i>0x47)&&(i<0x4e)) || - (i==0x4e) || ((i>0x59)&&(i<0x5c))) - continue; /* Skip absent or read-only registers */ - ioSet8(pciConfigSpace+i, 0x00, pci415e[i-0x41]); - } - - if (mi->BitsPerPlane == 16) { - if (mi->NumberGreenBits == 5) - ioSet8(pciConfigSpace+0x58, 0xfd, 0x00); /* 16bpp is 5:5:5 */ - else - ioSet8(pciConfigSpace+0x58, 0xfd, 0x02); /* 16bpp is 5:6:5 */ - } -} -/*****************************************************************************/ -static void setMiscOutputRegister(VIDEO_MODE_INFORMATION *mi) { -uint8 MiscOutputReg; - if (mi->VisScreenHeight < 400) - MiscOutputReg = 0x80; /* -vsync, +hsync */ - else if (mi->VisScreenHeight < 480) - MiscOutputReg = 0x40; /* +vsync, -hsync */ - else if (mi->VisScreenHeight < 768) - MiscOutputReg = 0xc0; /* -vsync, -hsync */ - else - MiscOutputReg = 0x00; /* +vsync, +hsync */ - ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0x3f) | MiscOutputReg); - - /* Enable host access to display memory, color mode */ - ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xfc) | 0x03); -} -/*****************************************************************************/ -static void setATC(uint8 bpp) { -uint8 atc[7] = {0x21, 0x00, 0x30, 0x00, 0x00}, atc16 = 0x80;/// -///uint8 atc[7] = {0x01, 0x00, 0x0f, 0x00, 0x00}, atc16 = 0x80;///zzz -uint8 i, atcIndexReg; -volatile uint8 f; - - f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */ - atcIndexReg = ioGet8(0x3c0) & 0xe0; /* Save bits[7:5] */ - - for (i = 0x10; i < 0x15; i++) { - f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */ - ioSet8(0x3c0, 0x00, i | atcIndexReg); - ioSet8(0x3c0, 0x00, atc[i-0x10]); - } - - switch (bpp) { - case 24: - atc16 |= 0x20; - break; - case 16: - atc16 |= 0x10; - break; - } - f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */ - ioSet8(0x3c0, 0x00, 0x16 | atcIndexReg); - ioSet8(0x3c0, 0x00, atc16); -} -/*****************************************************************************/ -static void setTS(void) { -uint8 ts[7] = {0x02, 0x01, 0x0f, 0x00, 0x0e, 0x00, 0x00}; -uint8 i; - - for (i = 0; i < 7; i++) { - if (i == 5) continue; /* Skip absent register */ - ioSet8(0x3c4, 0xf8, i); - ioSet8(0x3c5, 0x00, ts[i]); - } -} -/*****************************************************************************/ -static void setGDC(void) { -uint8 gdc[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff}; -uint8 i; - - for (i = 0; i < 9; i++) { - ioSet8(0x3ce, 0xf0, i); - ioSet8(0x3cf, 0x00, gdc[i]); - } -} -/*****************************************************************************/ -static void setClock0RegNum(uint8 regNum) { - /* Set bits[1:0] of the selected CLOCK0 PLL parameters register number */ - ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xf3) | ((regNum & 0x03) << 2)); - - /* Set bit[2] of the selected CLOCK0 PLL parameters register number */ - ioSet8(0x3d4, 0xc0, 0x34); - ioSet8(0x3d5, 0xfd, (regNum & 0x04) << 1); -} -/*****************************************************************************/ -static void setPLL(uint16 pciConfigSpace, - uint32 m) /* mode index */ -{ -uint8 regNum = 3; -uint8 clock0M = 0, clock0N = 0; - - clock0M = clock0MN[m].clock0M; - clock0N = clock0MN[m].clock0N; - - setClock0RegNum(regNum); - ioSet8(pciConfigSpace+0x67, 0x00, regNum); - ioSet8(pciConfigSpace+0x68, 0x00, regNum); - ioSet8(pciConfigSpace+0x69, 0x00, clock0M); - ioSet8(pciConfigSpace+0x69, 0x00, clock0N); -} -/*****************************************************************************/ -static void setCRTC(uint32 m) /* mode index */ -{ -uint8 i; - - /* Unlock the write protection of several registers */ - ioSet8(0x3d4, 0xc0, 0x11); - ioSet8(0x3d5, 0x7f, 0x00); - - for (i = 0; i < 64; i++) { - if (((i > 0x18) && (i < 0x33)) || - ((i > 0x35) && (i < 0x3f))) - continue; /* Skip absent or read-only registers */ - ioSet8(0x3d4, 0xc0, i); - ioSet8(0x3d5, 0x00, clock0MN[m].crtc[i]); - } -} -/*****************************************************************************/ -uint32 et6000SetGraphicsMode(VIDEO_MODE_INFORMATION *mi, - uint16 pciConfigSpace) -{ -uint8 m; - - for(m = 0; m < CLOCK0MN; m++) { - if ((clock0MN[m].width == mi->VisScreenWidth) && - (clock0MN[m].height == mi->VisScreenHeight) && - (clock0MN[m].bpp == mi->BitsPerPlane) && - ((clock0MN[m].refreshRate-1 <= mi->Frequency) && - (clock0MN[m].refreshRate+1 >= mi->Frequency))) - { - break; - } - } - if (m == CLOCK0MN) - return B_BAD_VALUE; /* Found no entry for requested mode */ - - et6000EnableLinearMemoryMapping(pciConfigSpace); - setMiscOutputRegister(mi); - ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */ - setPCIConfigSpaceRegisters41to5E(pciConfigSpace, mi, m); - ioSet8(0x3c6, 0x00, 0xff); /* Set pixel mask */ - setATC(mi->BitsPerPlane); - setTS(); - setGDC(); - setCRTC(m); - setPLL(pciConfigSpace, m); - - return B_OK; -} -/*****************************************************************************/ -status_t et6000SetMode(display_mode *mode, uint16 pciConfigSpace) { -VIDEO_MODE_INFORMATION mi; - - mi.VisScreenWidth = mode->virtual_width; - mi.VisScreenHeight = mode->virtual_height; - - switch (mode->space) { - case B_RGB24_LITTLE: - case B_RGB24_BIG: - mi.BitsPerPlane = 24; - mi.NumberGreenBits = 8; - break; - case B_RGB16_LITTLE: - case B_RGB16_BIG: - mi.BitsPerPlane = 16; - mi.NumberGreenBits = 6; - break; - case B_RGB15_LITTLE: - case B_RGB15_BIG: - mi.BitsPerPlane = 16; - mi.NumberGreenBits = 5; - break; - } - - mi.Frequency = (uint16) (mode->timing.pixel_clock * 1000 - / (mode->timing.h_total * mode->timing.v_total)); - - return et6000SetGraphicsMode(&mi, pciConfigSpace); -} -/*****************************************************************************/ -status_t et6000ProposeMode(display_mode *mode, uint32 memSize) { -uint8 m, bpp; -uint16 refreshRate; - - /* Framebuffer must not overlap with the memory mapped registers */ - if (memSize > 0x3fe000) - memSize = 0x3fe000; - - memSize -= ET6000_ACL_NEEDS_MEMORY; - - switch (mode->space) { - case B_RGB24_LITTLE: - case B_RGB24_BIG: - bpp = 24; - break; - case B_RGB16_LITTLE: - case B_RGB16_BIG: - case B_RGB15_LITTLE: - case B_RGB15_BIG: - bpp = 16; - break; - } - - refreshRate = (uint16) (mode->timing.pixel_clock * 1000 - / (mode->timing.h_total * mode->timing.v_total)); - - for(m = 0; m < CLOCK0MN; m++) { - if ((clock0MN[m].width == mode->virtual_width) && - (clock0MN[m].height == mode->virtual_height) && - (clock0MN[m].bpp == bpp) && - ((clock0MN[m].refreshRate-1 <= refreshRate) && - (clock0MN[m].refreshRate+1 >= refreshRate))) - { - break; - } - } - if (m == CLOCK0MN) - return B_BAD_VALUE; /* Found no entry for requested mode */ - - if (mode->virtual_width * mode->virtual_height * bpp / 8 > memSize) - return B_BAD_VALUE; /* Not enough adapter onboard memory */ - - return B_OK; -} -/*****************************************************************************/ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ + +#include "setmode.h" + + +/* + * ATTENTION: Currently we set the graphics modes by setting the registers + * with the beforehand dumped values of the corresponding registers. So not + * all graphics modes ET6x00 chips are capable of are accessible. So it would + * be great to implement the normal algorithm of run-time computing of the + * values to set the register. + */ + + +/*****************************************************************************/ +typedef struct { + uint32 VisScreenWidth; + uint32 VisScreenHeight; + uint8 BitsPerPlane; + uint8 NumberGreenBits; + uint16 Frequency; +} VIDEO_MODE_INFORMATION; +/*****************************************************************************/ +/* + * ATTENTION: Don't forget that CRTC indexed register 0x11 + * bit[7] write-protects some registers. + */ +struct { + uint16 width, height, bpp, refreshRate; + uint8 clock0M, clock0N; + uint8 pci42; /* contains MCLK divider (MDIV) */ + uint8 crtc[64]; +} clock0MN[] = { + {640, 480, 24, 75, 0x28, 0x22, 0x02, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + {640, 480, 24, 72, 0x56, 0x63, 0x00, + {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe8, 0x0b, 0xdf, 0xf0, 0x60, 0xe7, 0xff, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + {640, 480, 24, 60, 0x28, 0x22, 0x02, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x0c, 0xdf, 0xf0, 0x60, 0xe7, 0x04, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + + {640, 480, 16, 75, 0x56, 0x43, 0x01, + {0x64, 0x4f, 0x4f, 0x88, 0x54, 0x9c, 0xf2, 0x1f, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x03, 0xdf, 0xa0, 0x60, 0xdf, 0xf3, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + {640, 480, 16, 72, 0x56, 0x43, 0x01, + {0x63, 0x4f, 0x50, 0x86, 0x55, 0x9a, 0x06, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe8, 0x0b, 0xdf, 0xa0, 0x60, 0xe7, 0xff, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + {640, 480, 16, 60, 0x28, 0x41, 0x01, + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x0c, 0xdf, 0xa0, 0x60, 0xe7, 0x04, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + + {800, 600, 24, 75, 0x79, 0x49, 0x00, + {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, + {800, 600, 24, 72, 0x28, 0x41, 0x00, + {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x02, 0x57, 0x2c, 0x60, 0x57, 0x99, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, + {800, 600, 24, 60, 0x79, 0x49, 0x00, + {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0c, 0x57, 0x2c, 0x60, 0x57, 0x73, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, + + {800, 600, 16, 75, 0x51, 0x44, 0x00, + {0x7f, 0x63, 0x63, 0x83, 0x68, 0x12, 0x6f, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0b, 0x57, 0xc8, 0x60, 0x57, 0x70, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + {800, 600, 16, 72, 0x28, 0x41, 0x00, + {0x7d, 0x63, 0x63, 0x81, 0x6d, 0x1c, 0x98, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x02, 0x57, 0xc8, 0x60, 0x57, 0x99, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + {800, 600, 16, 60, 0x79, 0x49, 0x00, + {0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0c, 0x57, 0xc8, 0x60, 0x57, 0x73, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00}}, + + {1024, 768, 16, 75, 0x1f, 0x21, 0x00, + {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, + {1024, 768, 16, 70, 0x28, 0x22, 0x00, + {0x9f, 0x7f, 0x7f, 0x83, 0x84, 0x90, 0x1e, 0xf5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x83, 0xff, 0x00, 0x60, 0xff, 0x1f, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, + {1024, 768, 16, 60, 0x6b, 0x44, 0x00, + {0xa1, 0x7f, 0x80, 0x84, 0x88, 0x99, 0x26, 0xfd, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x0a, 0xff, 0x00, 0x60, 0x04, 0x22, 0xab, + 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80}}, +}; + +#define CLOCK0MN (sizeof(clock0MN) / sizeof(clock0MN[0])) +/*****************************************************************************/ +__inline void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace) +{ + /* + * Relocate memory via PCI Base Address 0; don't enable MMU; + * enable memory mapped registers; enable system linear memory mapping. + */ + ioSet8(pciConfigSpace+0x40, 0xf0, 0x0b); +} +/*****************************************************************************/ +static void setPCIConfigSpaceRegisters41to5E(uint16 pciConfigSpace, + VIDEO_MODE_INFORMATION *mi, + uint32 m) +{ +uint8 pci415e[30] = { + 0x3a, 0x00, 0x02, 0x15, 0x04, 0x40, 0x13, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}; +uint8 i; + + pci415e[1] = clock0MN[m].pci42; + + for (i=0x41; i<0x5f; i++) { + if ((i==0x45) || ((i>0x47)&&(i<0x4e)) || + (i==0x4e) || ((i>0x59)&&(i<0x5c))) + continue; /* Skip absent or read-only registers */ + ioSet8(pciConfigSpace+i, 0x00, pci415e[i-0x41]); + } + + if (mi->BitsPerPlane == 16) { + if (mi->NumberGreenBits == 5) + ioSet8(pciConfigSpace+0x58, 0xfd, 0x00); /* 16bpp is 5:5:5 */ + else + ioSet8(pciConfigSpace+0x58, 0xfd, 0x02); /* 16bpp is 5:6:5 */ + } +} +/*****************************************************************************/ +static void setMiscOutputRegister(VIDEO_MODE_INFORMATION *mi) { +uint8 MiscOutputReg; + if (mi->VisScreenHeight < 400) + MiscOutputReg = 0x80; /* -vsync, +hsync */ + else if (mi->VisScreenHeight < 480) + MiscOutputReg = 0x40; /* +vsync, -hsync */ + else if (mi->VisScreenHeight < 768) + MiscOutputReg = 0xc0; /* -vsync, -hsync */ + else + MiscOutputReg = 0x00; /* +vsync, +hsync */ + ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0x3f) | MiscOutputReg); + + /* Enable host access to display memory, color mode */ + ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xfc) | 0x03); +} +/*****************************************************************************/ +static void setATC(uint8 bpp) { +uint8 atc[7] = {0x21, 0x00, 0x30, 0x00, 0x00}, atc16 = 0x80;/// +///uint8 atc[7] = {0x01, 0x00, 0x0f, 0x00, 0x00}, atc16 = 0x80;///zzz +uint8 i, atcIndexReg; +volatile uint8 f; + + f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */ + atcIndexReg = ioGet8(0x3c0) & 0xe0; /* Save bits[7:5] */ + + for (i = 0x10; i < 0x15; i++) { + f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */ + ioSet8(0x3c0, 0x00, i | atcIndexReg); + ioSet8(0x3c0, 0x00, atc[i-0x10]); + } + + switch (bpp) { + case 24: + atc16 |= 0x20; + break; + case 16: + atc16 |= 0x10; + break; + } + f = ioGet8(0x3da); /* Set index/data flip-flop to index mode */ + ioSet8(0x3c0, 0x00, 0x16 | atcIndexReg); + ioSet8(0x3c0, 0x00, atc16); +} +/*****************************************************************************/ +static void setTS(void) { +uint8 ts[7] = {0x02, 0x01, 0x0f, 0x00, 0x0e, 0x00, 0x00}; +uint8 i; + + for (i = 0; i < 7; i++) { + if (i == 5) continue; /* Skip absent register */ + ioSet8(0x3c4, 0xf8, i); + ioSet8(0x3c5, 0x00, ts[i]); + } +} +/*****************************************************************************/ +static void setGDC(void) { +uint8 gdc[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff}; +uint8 i; + + for (i = 0; i < 9; i++) { + ioSet8(0x3ce, 0xf0, i); + ioSet8(0x3cf, 0x00, gdc[i]); + } +} +/*****************************************************************************/ +static void setClock0RegNum(uint8 regNum) { + /* Set bits[1:0] of the selected CLOCK0 PLL parameters register number */ + ioSet8(0x3c2, 0x00, (ioGet8(0x3cc) & 0xf3) | ((regNum & 0x03) << 2)); + + /* Set bit[2] of the selected CLOCK0 PLL parameters register number */ + ioSet8(0x3d4, 0xc0, 0x34); + ioSet8(0x3d5, 0xfd, (regNum & 0x04) << 1); +} +/*****************************************************************************/ +static void setPLL(uint16 pciConfigSpace, + uint32 m) /* mode index */ +{ +uint8 regNum = 3; +uint8 clock0M = 0, clock0N = 0; + + clock0M = clock0MN[m].clock0M; + clock0N = clock0MN[m].clock0N; + + setClock0RegNum(regNum); + ioSet8(pciConfigSpace+0x67, 0x00, regNum); + ioSet8(pciConfigSpace+0x68, 0x00, regNum); + ioSet8(pciConfigSpace+0x69, 0x00, clock0M); + ioSet8(pciConfigSpace+0x69, 0x00, clock0N); +} +/*****************************************************************************/ +static void setCRTC(uint32 m) /* mode index */ +{ +uint8 i; + + /* Unlock the write protection of several registers */ + ioSet8(0x3d4, 0xc0, 0x11); + ioSet8(0x3d5, 0x7f, 0x00); + + for (i = 0; i < 64; i++) { + if (((i > 0x18) && (i < 0x33)) || + ((i > 0x35) && (i < 0x3f))) + continue; /* Skip absent or read-only registers */ + ioSet8(0x3d4, 0xc0, i); + ioSet8(0x3d5, 0x00, clock0MN[m].crtc[i]); + } +} +/*****************************************************************************/ +uint32 et6000SetGraphicsMode(VIDEO_MODE_INFORMATION *mi, + uint16 pciConfigSpace) +{ +uint8 m; + + for(m = 0; m < CLOCK0MN; m++) { + if ((clock0MN[m].width == mi->VisScreenWidth) && + (clock0MN[m].height == mi->VisScreenHeight) && + (clock0MN[m].bpp == mi->BitsPerPlane) && + ((clock0MN[m].refreshRate-1 <= mi->Frequency) && + (clock0MN[m].refreshRate+1 >= mi->Frequency))) + { + break; + } + } + if (m == CLOCK0MN) + return B_BAD_VALUE; /* Found no entry for requested mode */ + + et6000EnableLinearMemoryMapping(pciConfigSpace); + setMiscOutputRegister(mi); + ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */ + setPCIConfigSpaceRegisters41to5E(pciConfigSpace, mi, m); + ioSet8(0x3c6, 0x00, 0xff); /* Set pixel mask */ + setATC(mi->BitsPerPlane); + setTS(); + setGDC(); + setCRTC(m); + setPLL(pciConfigSpace, m); + + return B_OK; +} +/*****************************************************************************/ +status_t et6000SetMode(display_mode *mode, uint16 pciConfigSpace) { +VIDEO_MODE_INFORMATION mi; + + mi.VisScreenWidth = mode->virtual_width; + mi.VisScreenHeight = mode->virtual_height; + + switch (mode->space) { + case B_RGB24_LITTLE: + case B_RGB24_BIG: + mi.BitsPerPlane = 24; + mi.NumberGreenBits = 8; + break; + case B_RGB16_LITTLE: + case B_RGB16_BIG: + mi.BitsPerPlane = 16; + mi.NumberGreenBits = 6; + break; + case B_RGB15_LITTLE: + case B_RGB15_BIG: + mi.BitsPerPlane = 16; + mi.NumberGreenBits = 5; + break; + } + + mi.Frequency = (uint16) (mode->timing.pixel_clock * 1000 + / (mode->timing.h_total * mode->timing.v_total)); + + return et6000SetGraphicsMode(&mi, pciConfigSpace); +} +/*****************************************************************************/ +status_t et6000ProposeMode(display_mode *mode, uint32 memSize) { +uint8 m, bpp; +uint16 refreshRate; + + /* Framebuffer must not overlap with the memory mapped registers */ + if (memSize > 0x3fe000) + memSize = 0x3fe000; + + memSize -= ET6000_ACL_NEEDS_MEMORY; + + switch (mode->space) { + case B_RGB24_LITTLE: + case B_RGB24_BIG: + bpp = 24; + break; + case B_RGB16_LITTLE: + case B_RGB16_BIG: + case B_RGB15_LITTLE: + case B_RGB15_BIG: + bpp = 16; + break; + } + + refreshRate = (uint16) (mode->timing.pixel_clock * 1000 + / (mode->timing.h_total * mode->timing.v_total)); + + for(m = 0; m < CLOCK0MN; m++) { + if ((clock0MN[m].width == mode->virtual_width) && + (clock0MN[m].height == mode->virtual_height) && + (clock0MN[m].bpp == bpp) && + ((clock0MN[m].refreshRate-1 <= refreshRate) && + (clock0MN[m].refreshRate+1 >= refreshRate))) + { + break; + } + } + if (m == CLOCK0MN) + return B_BAD_VALUE; /* Found no entry for requested mode */ + + if (mode->virtual_width * mode->virtual_height * bpp / 8 > memSize) + return B_BAD_VALUE; /* Not enough adapter onboard memory */ + + return B_OK; +} +/*****************************************************************************/ diff --git a/src/add-ons/kernel/drivers/graphics/et6x00/setmode.h b/src/add-ons/kernel/drivers/graphics/et6x00/setmode.h index a66bbd1260..1576888ed8 100644 --- a/src/add-ons/kernel/drivers/graphics/et6x00/setmode.h +++ b/src/add-ons/kernel/drivers/graphics/et6x00/setmode.h @@ -1,19 +1,19 @@ -/*****************************************************************************\ - * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. - * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. -\*****************************************************************************/ -#ifndef _ET6000SETMODE_H_ -#define _ET6000SETMODE_H_ - -#include "DriverInterface.h" -#include "bits.h" - - -/*****************************************************************************/ -__inline void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace); -status_t et6000SetMode(display_mode *mode, uint16 pciConfigSpace); -status_t et6000ProposeMode(display_mode *mode, uint32 memSize); -/*****************************************************************************/ - - -#endif /* _ET6000SETMODE_H_ */ +/*****************************************************************************\ + * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. + * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. +\*****************************************************************************/ +#ifndef _ET6000SETMODE_H_ +#define _ET6000SETMODE_H_ + +#include "DriverInterface.h" +#include "bits.h" + + +/*****************************************************************************/ +__inline void et6000EnableLinearMemoryMapping(uint16 pciConfigSpace); +status_t et6000SetMode(display_mode *mode, uint16 pciConfigSpace); +status_t et6000ProposeMode(display_mode *mode, uint32 memSize); +/*****************************************************************************/ + + +#endif /* _ET6000SETMODE_H_ */