1/*****************************************************************************\
2 * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
3 * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
4\*****************************************************************************/
5
6#include "GlobalData.h"
7#include "generic.h"
8
9#include "string.h"
10#include "unistd.h"
11#include "sys/types.h"
12#include "sys/stat.h"
13#include "fcntl.h"
14#include <sys/ioctl.h>
15
16
17/*****************************************************************************/
18/*
19 * Initialization code shared between primary and cloned accelerants.
20 */
21static status_t initCommon(int the_fd) {
22status_t result;
23ET6000GetPrivateData gpd;
24
25    /* memorize the file descriptor */
26    fd = the_fd;
27    /* set the magic number so the driver knows we're for real */
28    gpd.magic = ET6000_PRIVATE_DATA_MAGIC;
29    /* contact driver and get a pointer to the registers and shared data */
30    result = ioctl(fd, ET6000_GET_PRIVATE_DATA, &gpd, sizeof(gpd));
31    if (result != B_OK) goto error0;
32
33    /* clone the shared area for our use */
34    sharedInfoArea = clone_area("ET6000 shared info", (void **)&si,
35        B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gpd.sharedInfoArea);
36    if (sharedInfoArea < 0) {
37        result = sharedInfoArea;
38        goto error0;
39    }
40
41    mmRegs = si->mmRegs;
42
43error0:
44    return result;
45}
46/*****************************************************************************/
47/*
48 * Clean up code shared between primary and cloned accelrants.
49 */
50static void uninitCommon(void) {
51    /* release our copy of the shared info from the kernel driver */
52    delete_area(sharedInfoArea);
53    si = 0;
54}
55/*****************************************************************************/
56/*
57 * Initialize the accelerant.  the_fd is the file handle of the device
58 * (in /dev/graphics) that has been opened by the app_server (or some test
59 * harness). We need to determine if the kernel driver and the accelerant
60 * are compatible. If they are, get the accelerant ready to handle other
61 * hook functions and report success or failure.
62 */
63status_t INIT_ACCELERANT(int the_fd) {
64status_t result;
65
66    /* note that we're the primary accelerant (accelerantIsClone is global) */
67    accelerantIsClone = 0;
68
69    /* do the initialization common to both the primary and the clones */
70    result = initCommon(the_fd);
71
72    /* bail out if the common initialization failed */
73    if (result != B_OK) goto error0;
74
75    /* Call the device specific initialization code here, bail out if it failed */
76    if (result != B_OK) goto error1;
77
78    /*
79     * Now is a good time to figure out what video modes the card supports.
80     * We'll place the list of modes in another shared area so all
81     * of the copies of the driver can see them. The primary copy of the
82     * accelerant (ie the one initialized with this routine) will own the
83     * "one true copy" of the list. Everybody else get's a read-only clone.
84     */
85    result = createModesList();
86    if (result != B_OK) goto error2;
87
88    /*
89     * We store this info in a frame_buffer_config structure to
90     * make it convienient to return to the app_server later.
91     */
92    si->fbc.frame_buffer = si->framebuffer;
93    si->fbc.frame_buffer_dma = si->physFramebuffer;
94
95    /* init the shared semaphore */
96    INIT_BEN(si->engine.lock);
97
98    /* initialize the engine synchronization variables */
99
100    /* count of issued parameters or commands */
101    si->engine.lastIdle = si->engine.count = 0;
102
103    /* bail out if something failed */
104    if (result != B_OK) goto error3;
105
106    /* a winner! */
107    result = B_OK;
108    goto error0;
109
110error3:
111    /* free up the benaphore */
112    DELETE_BEN(si->engine.lock);
113
114error2:
115    /*
116     * Clean up any resources allocated in your device
117     * specific initialization code.
118     */
119
120error1:
121    /*
122     * Initialization failed after initCommon() succeeded, so we need to
123     * clean up before quiting.
124     */
125    uninitCommon();
126
127error0:
128    return result;
129}
130/*****************************************************************************/
131/*
132 * Return the number of bytes required to hold the information required
133 * to clone the device.
134 */
135ssize_t ACCELERANT_CLONE_INFO_SIZE(void) {
136    /*
137     * Since we're passing the name of the device as the only required
138     * info, return the size of the name buffer
139     */
140    return B_OS_NAME_LENGTH;
141}
142/*****************************************************************************/
143/*
144 * Return the info required to clone the device.  void *data points to
145 * a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length.
146 */
147void GET_ACCELERANT_CLONE_INFO(void *data) {
148ET6000DeviceName dn;
149status_t result;
150
151    /* call the kernel driver to get the device name */
152    dn.magic = ET6000_PRIVATE_DATA_MAGIC;
153    /* store the returned info directly into the passed buffer */
154    dn.name = (char *)data;
155    result = ioctl(fd, ET6000_DEVICE_NAME, &dn, sizeof(dn));
156}
157/*****************************************************************************/
158/*
159 * Initialize a copy of the accelerant as a clone.  void *data points
160 * to a copy of the data returned by GET_ACCELERANT_CLONE_INFO().
161 */
162status_t CLONE_ACCELERANT(void *data) {
163status_t result;
164char path[MAXPATHLEN];
165
166    /* the data is the device name */
167    strcpy(path, "/dev/");
168    strcat(path, (const char *)data);
169    /* open the device, the permissions aren't important */
170    fd = open(path, B_READ_WRITE);
171    if (fd < 0) {
172        result = fd;
173        goto error0;
174    }
175
176    /* note that we're a clone accelerant */
177    accelerantIsClone = 1;
178
179    /* call the shared initialization code */
180    result = initCommon(fd);
181
182    /* bail out if the common initialization failed */
183    if (result != B_OK) goto error1;
184
185    /* get shared area for display modes */
186    result = et6000ModesListArea = clone_area("ET6000 cloned display_modes",
187        (void **)&et6000ModesList, B_ANY_ADDRESS, B_READ_AREA, si->modesArea);
188    if (result < B_OK) goto error2;
189
190    /* all done */
191    result = B_OK;
192    goto error0;
193
194error2:
195    /* free up the areas we cloned */
196    uninitCommon();
197error1:
198    /* close the device we opened */
199    close(fd);
200error0:
201    return result;
202}
203/*****************************************************************************/
204void UNINIT_ACCELERANT(void) {
205    /* free our mode list area */
206    delete_area(et6000ModesListArea);
207    et6000ModesList = 0;
208
209    /* release our cloned data */
210    uninitCommon();
211
212    /* close the file handle ONLY if we're the clone */
213    if (accelerantIsClone) close(fd);
214}
215/*****************************************************************************/
216status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi)
217{
218    adi->version = B_ACCELERANT_VERSION;
219    strcpy(adi->name, "Tseng Labs ET6x00");
220    strcpy(adi->chipset, "Tseng Labs ET6x00");
221    strcpy(adi->serial_no, "");
222    adi->memory = si->memSize;
223    adi->dac_speed = si->pixelClockMax16;
224
225    return B_OK;
226}
227/*****************************************************************************/
228