1/*
2 *
3 * Copyright (c) 1997  Metro Link Incorporated
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Except as contained in this notice, the name of the Metro Link shall not be
24 * used in advertising or otherwise to promote the sale, use or other dealings
25 * in this Software without prior written authorization from Metro Link.
26 *
27 */
28/*
29 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice shall be included in
39 * all copies or substantial portions of the Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
44 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
45 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
46 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
47 * OTHER DEALINGS IN THE SOFTWARE.
48 *
49 * Except as contained in this notice, the name of the copyright holder(s)
50 * and author(s) shall not be used in advertising or otherwise to promote
51 * the sale, use or other dealings in this Software without prior written
52 * authorization from the copyright holder(s) and author(s).
53 */
54
55#ifdef HAVE_XORG_CONFIG_H
56#include <xorg-config.h>
57#endif
58
59#include "xf86Parser.h"
60#include "xf86tokens.h"
61#include "Configint.h"
62
63
64static const xf86ConfigSymTabRec DeviceTab[] = {
65    {ENDSECTION, "endsection"},
66    {IDENTIFIER, "identifier"},
67    {VENDOR, "vendorname"},
68    {BOARD, "boardname"},
69    {CHIPSET, "chipset"},
70    {RAMDAC, "ramdac"},
71    {DACSPEED, "dacspeed"},
72    {CLOCKS, "clocks"},
73    {MATCHSEAT, "matchseat"},
74    {OPTION, "option"},
75    {VIDEORAM, "videoram"},
76    {BIOSBASE, "biosbase"},
77    {MEMBASE, "membase"},
78    {IOBASE, "iobase"},
79    {CLOCKCHIP, "clockchip"},
80    {CHIPID, "chipid"},
81    {CHIPREV, "chiprev"},
82    {CARD, "card"},
83    {DRIVER, "driver"},
84    {BUSID, "busid"},
85    {IRQ, "irq"},
86    {SCREEN, "screen"},
87    {-1, ""},
88};
89
90#define CLEANUP xf86freeDeviceList
91
92XF86ConfDevicePtr
93xf86parseDeviceSection(void)
94{
95    int i;
96    int has_ident = FALSE;
97    int token;
98
99    parsePrologue(XF86ConfDevicePtr, XF86ConfDeviceRec)
100
101        /* Zero is a valid value for these */
102        ptr->dev_chipid = -1;
103    ptr->dev_chiprev = -1;
104    ptr->dev_irq = -1;
105    while ((token = xf86getToken(DeviceTab)) != ENDSECTION) {
106        switch (token) {
107        case COMMENT:
108            ptr->dev_comment = xf86addComment(ptr->dev_comment, xf86_lex_val.str);
109            free(xf86_lex_val.str);
110            xf86_lex_val.str = NULL;
111            break;
112        case IDENTIFIER:
113            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
114                Error(QUOTE_MSG, "Identifier");
115            if (has_ident == TRUE)
116                Error(MULTIPLE_MSG, "Identifier");
117            ptr->dev_identifier = xf86_lex_val.str;
118            has_ident = TRUE;
119            break;
120        case VENDOR:
121            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
122                Error(QUOTE_MSG, "Vendor");
123            ptr->dev_vendor = xf86_lex_val.str;
124            break;
125        case BOARD:
126            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
127                Error(QUOTE_MSG, "Board");
128            ptr->dev_board = xf86_lex_val.str;
129            break;
130        case CHIPSET:
131            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
132                Error(QUOTE_MSG, "Chipset");
133            ptr->dev_chipset = xf86_lex_val.str;
134            break;
135        case CARD:
136            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
137                Error(QUOTE_MSG, "Card");
138            ptr->dev_card = xf86_lex_val.str;
139            break;
140        case DRIVER:
141            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
142                Error(QUOTE_MSG, "Driver");
143            ptr->dev_driver = xf86_lex_val.str;
144            break;
145        case RAMDAC:
146            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
147                Error(QUOTE_MSG, "Ramdac");
148            ptr->dev_ramdac = xf86_lex_val.str;
149            break;
150        case DACSPEED:
151            for (i = 0; i < CONF_MAXDACSPEEDS; i++)
152                ptr->dev_dacSpeeds[i] = 0;
153            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER) {
154                Error(DACSPEED_MSG, CONF_MAXDACSPEEDS);
155            }
156            else {
157                ptr->dev_dacSpeeds[0] = (int) (xf86_lex_val.realnum * 1000.0 + 0.5);
158                for (i = 1; i < CONF_MAXDACSPEEDS; i++) {
159                    if (xf86getSubToken(&(ptr->dev_comment)) == NUMBER)
160                        ptr->dev_dacSpeeds[i] = (int)
161                            (xf86_lex_val.realnum * 1000.0 + 0.5);
162                    else {
163                        xf86unGetToken(token);
164                        break;
165                    }
166                }
167            }
168            break;
169        case VIDEORAM:
170            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
171                Error(NUMBER_MSG, "VideoRam");
172            ptr->dev_videoram = xf86_lex_val.num;
173            break;
174        case BIOSBASE:
175            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
176                Error(NUMBER_MSG, "BIOSBase");
177            /* ignored */
178            break;
179        case MEMBASE:
180            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
181                Error(NUMBER_MSG, "MemBase");
182            ptr->dev_mem_base = xf86_lex_val.num;
183            break;
184        case IOBASE:
185            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
186                Error(NUMBER_MSG, "IOBase");
187            ptr->dev_io_base = xf86_lex_val.num;
188            break;
189        case CLOCKCHIP:
190            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
191                Error(QUOTE_MSG, "ClockChip");
192            ptr->dev_clockchip = xf86_lex_val.str;
193            break;
194        case CHIPID:
195            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
196                Error(NUMBER_MSG, "ChipID");
197            ptr->dev_chipid = xf86_lex_val.num;
198            break;
199        case CHIPREV:
200            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
201                Error(NUMBER_MSG, "ChipRev");
202            ptr->dev_chiprev = xf86_lex_val.num;
203            break;
204
205        case CLOCKS:
206            token = xf86getSubToken(&(ptr->dev_comment));
207            for (i = ptr->dev_clocks;
208                 token == NUMBER && i < CONF_MAXCLOCKS; i++) {
209                ptr->dev_clock[i] = (int) (xf86_lex_val.realnum * 1000.0 + 0.5);
210                token = xf86getSubToken(&(ptr->dev_comment));
211            }
212            ptr->dev_clocks = i;
213            xf86unGetToken(token);
214            break;
215        case MATCHSEAT:
216            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
217                Error(QUOTE_MSG, "MatchSeat");
218            ptr->match_seat = xf86_lex_val.str;
219            break;
220        case OPTION:
221            ptr->dev_option_lst = xf86parseOption(ptr->dev_option_lst);
222            break;
223        case BUSID:
224            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
225                Error(QUOTE_MSG, "BusID");
226            ptr->dev_busid = xf86_lex_val.str;
227            break;
228        case IRQ:
229            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
230                Error(QUOTE_MSG, "IRQ");
231            ptr->dev_irq = xf86_lex_val.num;
232            break;
233        case SCREEN:
234            if (xf86getSubToken(&(ptr->dev_comment)) != NUMBER)
235                Error(NUMBER_MSG, "Screen");
236            ptr->dev_screen = xf86_lex_val.num;
237            break;
238        case EOF_TOKEN:
239            Error(UNEXPECTED_EOF_MSG);
240            break;
241        default:
242            Error(INVALID_KEYWORD_MSG, xf86tokenString());
243            break;
244        }
245    }
246
247    if (!has_ident)
248        Error(NO_IDENT_MSG);
249
250#ifdef DEBUG
251    printf("Device section parsed\n");
252#endif
253
254    return ptr;
255}
256
257#undef CLEANUP
258
259void
260xf86printDeviceSection(FILE * cf, XF86ConfDevicePtr ptr)
261{
262    int i;
263
264    while (ptr) {
265        fprintf(cf, "Section \"Device\"\n");
266        if (ptr->dev_comment)
267            fprintf(cf, "%s", ptr->dev_comment);
268        if (ptr->dev_identifier)
269            fprintf(cf, "\tIdentifier  \"%s\"\n", ptr->dev_identifier);
270        if (ptr->dev_driver)
271            fprintf(cf, "\tDriver      \"%s\"\n", ptr->dev_driver);
272        if (ptr->dev_vendor)
273            fprintf(cf, "\tVendorName  \"%s\"\n", ptr->dev_vendor);
274        if (ptr->dev_board)
275            fprintf(cf, "\tBoardName   \"%s\"\n", ptr->dev_board);
276        if (ptr->dev_chipset)
277            fprintf(cf, "\tChipSet     \"%s\"\n", ptr->dev_chipset);
278        if (ptr->dev_card)
279            fprintf(cf, "\tCard        \"%s\"\n", ptr->dev_card);
280        if (ptr->dev_ramdac)
281            fprintf(cf, "\tRamDac      \"%s\"\n", ptr->dev_ramdac);
282        if (ptr->dev_dacSpeeds[0] > 0) {
283            fprintf(cf, "\tDacSpeed    ");
284            for (i = 0; i < CONF_MAXDACSPEEDS && ptr->dev_dacSpeeds[i] > 0; i++)
285                fprintf(cf, "%g ", (double) (ptr->dev_dacSpeeds[i]) / 1000.0);
286            fprintf(cf, "\n");
287        }
288        if (ptr->dev_videoram)
289            fprintf(cf, "\tVideoRam    %d\n", ptr->dev_videoram);
290        if (ptr->dev_mem_base)
291            fprintf(cf, "\tMemBase     0x%lx\n", ptr->dev_mem_base);
292        if (ptr->dev_io_base)
293            fprintf(cf, "\tIOBase      0x%lx\n", ptr->dev_io_base);
294        if (ptr->dev_clockchip)
295            fprintf(cf, "\tClockChip   \"%s\"\n", ptr->dev_clockchip);
296        if (ptr->dev_chipid != -1)
297            fprintf(cf, "\tChipId      0x%x\n", ptr->dev_chipid);
298        if (ptr->dev_chiprev != -1)
299            fprintf(cf, "\tChipRev     0x%x\n", ptr->dev_chiprev);
300
301        xf86printOptionList(cf, ptr->dev_option_lst, 1);
302        if (ptr->dev_clocks > 0) {
303            fprintf(cf, "\tClocks      ");
304            for (i = 0; i < ptr->dev_clocks; i++)
305                fprintf(cf, "%.1f ", (double) ptr->dev_clock[i] / 1000.0);
306            fprintf(cf, "\n");
307        }
308        if (ptr->dev_busid)
309            fprintf(cf, "\tBusID       \"%s\"\n", ptr->dev_busid);
310        if (ptr->dev_screen > 0)
311            fprintf(cf, "\tScreen      %d\n", ptr->dev_screen);
312        if (ptr->dev_irq >= 0)
313            fprintf(cf, "\tIRQ         %d\n", ptr->dev_irq);
314        fprintf(cf, "EndSection\n\n");
315        ptr = ptr->list.next;
316    }
317}
318
319void
320xf86freeDeviceList(XF86ConfDevicePtr ptr)
321{
322    XF86ConfDevicePtr prev;
323
324    while (ptr) {
325        TestFree(ptr->dev_identifier);
326        TestFree(ptr->dev_vendor);
327        TestFree(ptr->dev_board);
328        TestFree(ptr->dev_chipset);
329        TestFree(ptr->dev_card);
330        TestFree(ptr->dev_driver);
331        TestFree(ptr->dev_ramdac);
332        TestFree(ptr->dev_clockchip);
333        TestFree(ptr->dev_comment);
334        xf86optionListFree(ptr->dev_option_lst);
335
336        prev = ptr;
337        ptr = ptr->list.next;
338        free(prev);
339    }
340}
341
342XF86ConfDevicePtr
343xf86findDevice(const char *ident, XF86ConfDevicePtr p)
344{
345    while (p) {
346        if (xf86nameCompare(ident, p->dev_identifier) == 0)
347            return p;
348
349        p = p->list.next;
350    }
351    return NULL;
352}
353
354XF86ConfDevicePtr
355xf86findDeviceByDriver (const char *driver, XF86ConfDevicePtr p)
356{
357	while (p)
358	{
359		if (xf86nameCompare (driver, p->dev_driver) == 0)
360			return p;
361
362		p = p->list.next;
363	}
364	return NULL;
365}
366