xref: /haiku/src/add-ons/accelerants/et6x00/InitAccelerant.c (revision 893988af824e65e49e55f517b157db8386e8002b)
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  */
21 static status_t initCommon(int the_fd) {
22 status_t result;
23 ET6000GetPrivateData 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 
43 error0:
44     return result;
45 }
46 /*****************************************************************************/
47 /*
48  * Clean up code shared between primary and cloned accelrants.
49  */
50 static 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  */
63 status_t INIT_ACCELERANT(int the_fd) {
64 status_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 
110 error3:
111     /* free up the benaphore */
112     DELETE_BEN(si->engine.lock);
113 
114 error2:
115     /*
116      * Clean up any resources allocated in your device
117      * specific initialization code.
118      */
119 
120 error1:
121     /*
122      * Initialization failed after initCommon() succeeded, so we need to
123      * clean up before quiting.
124      */
125     uninitCommon();
126 
127 error0:
128     return result;
129 }
130 /*****************************************************************************/
131 /*
132  * Return the number of bytes required to hold the information required
133  * to clone the device.
134  */
135 ssize_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  */
147 void GET_ACCELERANT_CLONE_INFO(void *data) {
148 ET6000DeviceName dn;
149 status_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  */
162 status_t CLONE_ACCELERANT(void *data) {
163 status_t result;
164 char 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 
194 error2:
195     /* free up the areas we cloned */
196     uninitCommon();
197 error1:
198     /* close the device we opened */
199     close(fd);
200 error0:
201     return result;
202 }
203 /*****************************************************************************/
204 void 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 /*****************************************************************************/
216 status_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