xref: /haiku/src/add-ons/kernel/drivers/graphics/et6x00/driver.c (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*****************************************************************************\
2  * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5.
3  * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov.
4 \*****************************************************************************/
5 
6 /* standard kernel driver stuff */
7 #include <KernelExport.h>
8 #include <PCI.h>
9 #include <OS.h>
10 #include <malloc.h>
11 
12 /* this is for the standardized portion of the driver API */
13 /* currently only one operation is defined: B_GET_ACCELERANT_SIGNATURE */
14 #include <graphic_driver.h>
15 
16 /* this is for sprintf() */
17 #include <stdio.h>
18 
19 /* this is for string compares */
20 #include <string.h>
21 
22 /* The private interface between the accelerant and the kernel driver. */
23 #include "DriverInterface.h"
24 
25 #include "setmode.h"
26 #include "acl.h"
27 #include "bits.h"
28 
29 /*****************************************************************************/
30 #if DEBUG > 0
31 #define ddprintf(a)     dprintf a
32 #else
33 #define ddprintf(a)
34 #endif
35 
36 #define MAX_DEVICES     8
37 
38 /* Tell the kernel what revision of the driver API we support */
39 int32   api_version = 2;
40 
41 /*****************************************************************************/
42 /* This structure is private to the kernel driver */
43 typedef struct {
44     uint32 isOpen; /* a count of how many times the devices has been opened */
45     area_id sharedArea; /* the area shared between the driver and all of the accelerants */
46     ET6000SharedInfo *si; /* a pointer to the shared area, for convenience */
47 #if DEBUG > 0
48     uint32 interrupt_count; /* if we're debugging, a count of how many times
49                        the interrupt handler has been called for this device */
50 #endif
51     pci_info pcii; /* a convenience copy of the pci info for this device */
52     char name[B_OS_NAME_LENGTH]; /* where we keep the name of the device for publishing and comparing */
53 } ET6000DeviceInfo;
54 /*****************************************************************************/
55 typedef struct {
56 #if DEBUG > 0
57     uint32 total_interrupts; /* total number of interrupts seen by our handler */
58 #endif
59     uint32 count; /* number of devices actually found */
60     benaphore kernel; /* for serializing opens/closes */
61     char *deviceNames[MAX_DEVICES+1]; /* device name pointer storage */
62     ET6000DeviceInfo di[MAX_DEVICES]; /* device specific stuff */
63 } DeviceData;
64 /*****************************************************************************/
65 static DeviceData *pd;
66 /*****************************************************************************/
67 /* prototypes for our private functions */
68 static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie);
69 static status_t et6000CloseHook(void* dev);
70 static status_t et6000FreeHook(void* dev);
71 static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len);
72 static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len);
73 static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len);
74 static status_t et6000MapDevice(ET6000DeviceInfo *di);
75 static void et6000UnmapDevice(ET6000DeviceInfo *di);
76 static void et6000ProbeDevices(void);
77 static int32 et6000Interrupt(void *data);
78 
79 #if DEBUG > 0
80 static int et6000dump(int argc, char **argv);
81 #endif
82 /*****************************************************************************/
83 static pci_module_info *pci_bus;
84 
85 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
86 
87 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
88 /*****************************************************************************/
89 static device_hooks et6000DeviceHooks = {
90     et6000OpenHook,
91     et6000CloseHook,
92     et6000FreeHook,
93     et6000ControlHook,
94     et6000ReadHook,
95     et6000WriteHook,
96     NULL,
97     NULL,
98     NULL,
99     NULL
100 };
101 /*****************************************************************************/
102 #define TSENG_VENDOR_ID 0x100C /* Tseng Labs Inc */
103 
104 static uint16 et6000DeviceList[] = {
105     0x3208, /* ET6000/ET6100 */
106     0x4702, /* ET6300 */
107     0
108 };
109 
110 static struct {
111     uint16  vendor;
112     uint16  *devices;
113 } supportedDevices[] = {
114     {TSENG_VENDOR_ID, et6000DeviceList},
115     {0x0000, NULL}
116 };
117 /*****************************************************************************/
118 /*
119  * Returns B_OK if one is found, otherwise returns
120  * B_ERROR so the driver will be unloaded.
121  */
122 status_t init_hardware(void) {
123 long pciIndex = 0;
124 pci_info pcii;
125 bool foundOne = FALSE;
126 
127     /* choke if we can't find the PCI bus */
128     if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
129         return B_ERROR;
130 
131     /* while there are more pci devices */
132     while ((*pci_bus->get_nth_pci_info)(pciIndex, &pcii) == B_NO_ERROR) {
133         int vendor = 0;
134 
135         ddprintf(("ET6000 init_hardware(): checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, pcii.vendor_id, pcii.device_id));
136         /* if we match a supported vendor */
137         while (supportedDevices[vendor].vendor) {
138             if (supportedDevices[vendor].vendor == pcii.vendor_id) {
139                 uint16 *devices = supportedDevices[vendor].devices;
140                 /* while there are more supported devices */
141                 while (*devices) {
142                     /* if we match a supported device */
143                     if (*devices == pcii.device_id) {
144                         ddprintf(("ET6000: we support this device\n"));
145                         foundOne = TRUE;
146                         goto done;
147                     }
148                     /* next supported device */
149                     devices++;
150                 }
151             }
152             vendor++;
153         }
154         /* next pci_info struct, please */
155         pciIndex++;
156     }
157     ddprintf(("ET6000: init_hardware - no supported devices\n"));
158 
159 done:
160     /* put away the module manager */
161     put_module(B_PCI_MODULE_NAME);
162     return (foundOne ? B_OK : B_ERROR);
163 }
164 /*****************************************************************************/
165 static void et6000ProbeDevices(void) {
166 uint32 pciIndex = 0;
167 uint32 count = 0;
168 ET6000DeviceInfo *di = pd->di;
169 
170     /* while there are more pci devices */
171     while ((count < MAX_DEVICES) &&
172         ((*pci_bus->get_nth_pci_info)(pciIndex, &(di->pcii)) == B_NO_ERROR))
173     {
174         int vendor = 0;
175 
176         ddprintf(("ET6000: checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, di->pcii.vendor_id, di->pcii.device_id));
177         /* if we match a supported vendor */
178         while (supportedDevices[vendor].vendor) {
179             if (supportedDevices[vendor].vendor == di->pcii.vendor_id) {
180                 uint16 *devices = supportedDevices[vendor].devices;
181                 /* while there are more supported devices */
182                 while (*devices) {
183                     /* if we match a supported device */
184                     if (*devices == di->pcii.device_id) {
185                         /* publish the device name */
186                         sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X",
187                                 di->pcii.vendor_id, di->pcii.device_id,
188                                 di->pcii.bus, di->pcii.device, di->pcii.function);
189                         ddprintf(("ET6000: making /dev/%s\n", di->name));
190                         /* remember the name */
191                         pd->deviceNames[count] = di->name;
192                         /* mark the driver as available for R/W open */
193                         di->isOpen = 0;
194                         /* mark areas as not yet created */
195                         di->sharedArea = -1;
196                         /* mark pointer to shared data as invalid */
197                         di->si = NULL;
198                         /* inc pointer to device info */
199                         di++;
200                         /* inc count */
201                         count++;
202                         /* break out of these while loops */
203                         goto next_device;
204                     }
205                     /* next supported device */
206                     devices++;
207                 }
208             }
209             vendor++;
210         }
211 next_device:
212         /* next pci_info struct, please */
213         pciIndex++;
214     }
215     /* propagate count */
216     pd->count = count;
217     /* terminate list of device names with a null pointer */
218     pd->deviceNames[pd->count] = NULL;
219     ddprintf(("SKD et6000ProbeDevices: %ld supported devices\n", pd->count));
220 }
221 /*****************************************************************************/
222 status_t init_driver(void) {
223     /* get a handle for the pci bus */
224     if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
225         return B_ERROR;
226 
227     /* driver private data */
228     pd = (DeviceData *)calloc(1, sizeof(DeviceData));
229     if (!pd) {
230         put_module(B_PCI_MODULE_NAME);
231         return B_ERROR;
232     }
233     /* initialize the benaphore */
234     INIT_BEN(pd->kernel);
235 
236     /* find all of our supported devices */
237     et6000ProbeDevices();
238 
239 #if DEBUG > 0
240     add_debugger_command("et6000dump", et6000dump, "dump ET6000 kernel driver persistant data");
241 #endif
242 
243     return B_OK;
244 }
245 /*****************************************************************************/
246 const char **publish_devices(void) {
247     /* return the list of supported devices */
248     return (const char **)pd->deviceNames;
249 }
250 /*****************************************************************************/
251 device_hooks *find_device(const char *name) {
252 int index = 0;
253     while (pd->deviceNames[index]) {
254         if (strcmp(name, pd->deviceNames[index]) == 0)
255             return &et6000DeviceHooks;
256         index++;
257     }
258     return NULL;
259 }
260 /*****************************************************************************/
261 void uninit_driver(void) {
262 
263 #if DEBUG > 0
264     remove_debugger_command("et6000dump", et6000dump);
265 #endif
266 
267     /* free the driver data */
268     DELETE_BEN(pd->kernel);
269     free(pd);
270     pd = NULL;
271 
272     /* put the pci module away */
273     put_module(B_PCI_MODULE_NAME);
274 }
275 /*****************************************************************************/
276 static int32 et6000Interrupt(void *data) {
277 int32 handled = B_UNHANDLED_INTERRUPT;
278 ET6000DeviceInfo *di = (ET6000DeviceInfo *)data;
279 ET6000SharedInfo *si = di->si;
280 int32 *flags = &(si->flags);
281 
282 #if DEBUG > 0
283     pd->total_interrupts++;
284 #endif
285 
286     /* is someone already handling an interrupt for this device? */
287     if (atomic_or(flags, ET6000_HANDLER_INSTALLED) & ET6000_HANDLER_INSTALLED) {
288 #if DEBUG > 0
289         kprintf("ET6000: Already in handler!\n");
290 #endif
291         goto exit0;
292     }
293 
294     switch (et6000aclInterruptCause(si->mmRegs)) {
295     case ET6000_ACL_INT_CAUSE_NONE:
296         handled = B_UNHANDLED_INTERRUPT;
297         break;
298     case ET6000_ACL_INT_CAUSE_READ:
299         et6000aclReadInterruptClear(si->mmRegs);
300         handled = B_HANDLED_INTERRUPT;
301         break;
302     case ET6000_ACL_INT_CAUSE_WRITE:
303         et6000aclWriteInterruptClear(si->mmRegs);
304         handled = B_HANDLED_INTERRUPT;
305         break;
306     case ET6000_ACL_INT_CAUSE_BOTH: /* Can it be at all? */
307         et6000aclReadInterruptClear(si->mmRegs);
308         et6000aclWriteInterruptClear(si->mmRegs);
309         handled = B_HANDLED_INTERRUPT;
310         break;
311     }
312 
313 #if DEBUG > 0
314     /* increment the counter for this device */
315     if (handled == B_HANDLED_INTERRUPT)
316         di->interrupt_count++;
317 #endif
318 
319     /* note that we're not in the handler any more */
320     atomic_and(flags, ~ET6000_HANDLER_INSTALLED);
321 
322 exit0:
323     return handled;
324 }
325 /*****************************************************************************/
326 static uint32 et6000GetOnboardMemorySize(uint16 pciConfigSpace,
327                                   volatile void *memory)
328 {
329 uint32 memSize = 0;
330 
331     ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */
332     ioSet8(0x3b8, 0x00, 0xa0); /* Set the KEY for monochrome modes */
333 
334     switch (ioGet8(0x3C2) & 0x03) {
335     case 0x00: /* onboard memory is of DRAM type */
336         memSize = 1024*1024 * ((ioGet8(pciConfigSpace + 0x45) & 0x03) + 1);
337         break;
338     case 0x03: /* onboard memory is of MDRAM type */
339         memSize = /* number*8 of 32kb banks per channel */
340             ((ioGet8(pciConfigSpace + 0x47) & 0x07) + 1) * 8 * 32*1024;
341         if (ioGet8(pciConfigSpace + 0x45) & 0x04) /* If 2 channels */
342             memSize *= 2;
343         break;
344     default:  /* onboard memory is of unknown type */
345         memSize = 4196*1024; /* Let it be of maximum possible size */
346     }
347 
348     /*
349      * This algorithm would fail to recongize 2.25Mb of onboard
350      * memory - it would detect 2.5Mb instead. It needs to be fixed.
351      */
352     if (memSize == 2621440) { /* If 2.5Mb detected */
353         uint8 pci40 = ioGet8(pciConfigSpace+0x40);
354         et6000EnableLinearMemoryMapping(pciConfigSpace);
355 
356         /* Check whether the memory beyond 2.25Mb really exists */
357         *(volatile uint32 *)((uint32)memory + 2359296) = 0xaa55aa55;
358         if (*(volatile uint32 *)((uint32)memory + 2359296) != 0xaa55aa55)
359             memSize = 2359296; /* It's 2.25Mb */
360 
361         ioSet8(pciConfigSpace+0x40, 0x00, pci40); /* Restore */
362     }
363 
364     return memSize;
365 }
366 /*****************************************************************************/
367 static status_t et6000MapDevice(ET6000DeviceInfo *di) {
368 char buffer[B_OS_NAME_LENGTH];
369 ET6000SharedInfo *si = di->si;
370 uint32  tmpUlong;
371 pci_info *pcii = &(di->pcii);
372 
373     /* Enable memory space access and I/O space access */
374     tmpUlong = get_pci(PCI_command, 4);
375     tmpUlong |= 0x00000003;
376     set_pci(PCI_command, 4, tmpUlong);
377 
378     /* Enable ROM decoding */
379     tmpUlong = get_pci(PCI_rom_base, 4);
380     tmpUlong |= 0x00000001;
381     set_pci(PCI_rom_base, 4, tmpUlong);
382 
383     /* PCI header base address in I/O space */
384     si->pciConfigSpace = (uint16)di->pcii.u.h0.base_registers[1];
385 
386     sprintf(buffer, "%04X_%04X_%02X%02X%02X videomemory",
387         di->pcii.vendor_id, di->pcii.device_id,
388         di->pcii.bus, di->pcii.device, di->pcii.function);
389 
390    /*
391     * We map the whole graphics card memory area (which consist of RAM memory
392     * and memory mapped registers) at once. Memory mapped registers must not
393     * be cacheble, so the whole area is mapped with B_MTR_UC (unable caching).
394     * We certainly could map separately the RAM memory with write combining
395     * (B_MTR_WC) and the memory mapped registers with B_MTR_UC.
396     */
397     si->memoryArea = map_physical_memory(buffer,
398         di->pcii.u.h0.base_registers[0],
399         di->pcii.u.h0.base_register_sizes[0],
400         B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_UC,
401         B_READ_AREA + B_WRITE_AREA,
402         &(si->memory));
403 
404     si->framebuffer = si->memory;
405     si->mmRegs = (void *)((uint32)si->memory + 0x003fff00);
406     si->emRegs = (void *)((uint32)si->memory + 0x003fe000);
407 
408     /* remember the physical addresses */
409     si->physMemory = si->physFramebuffer =
410         (void *) di->pcii.u.h0.base_registers_pci[0];
411 
412     si->memSize = et6000GetOnboardMemorySize(si->pciConfigSpace, si->memory);
413 
414     /* in any case, return the result */
415     return si->memoryArea;
416 }
417 /*****************************************************************************/
418 static void et6000UnmapDevice(ET6000DeviceInfo *di) {
419 ET6000SharedInfo *si = di->si;
420 
421     ddprintf(("et6000UnmapDevice(%08lx) begins...\n", (uint32)di));
422     ddprintf((" memoryArea: %ld\n", si->memoryArea));
423 
424     if (si->memoryArea >= 0)
425         delete_area(si->memoryArea);
426     si->memoryArea = -1;
427     si->framebuffer = NULL;
428     si->physFramebuffer = NULL;
429     si->memory = NULL;
430     si->physMemory = NULL;
431 
432     ddprintf(("et6000UnmapDevice() ends.\n"));
433 }
434 /*****************************************************************************/
435 static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie) {
436 int32 index = 0;
437 ET6000DeviceInfo *di;
438 ET6000SharedInfo *si;
439 status_t        result = B_OK;
440 char shared_name[B_OS_NAME_LENGTH];
441 
442     ddprintf(("SKD et6000OpenHook(%s, %ld, 0x%08lx)\n", name, flags, (uint32)cookie));
443 
444     /* find the device name in the list of devices */
445     /* we're never passed a name we didn't publish */
446     while(pd->deviceNames[index] &&
447          (strcmp(name, pd->deviceNames[index]) != 0))
448     {
449         index++;
450     }
451 
452     /* for convienience */
453     di = &(pd->di[index]);
454 
455     /* make sure no one else has write access to the common data */
456     AQUIRE_BEN(pd->kernel);
457 
458     /* if it's already open for writing */
459     if (di->isOpen) {
460         /* mark it open another time */
461         goto mark_as_open;
462     }
463     /* create the shared area */
464     sprintf(shared_name, "%04X_%04X_%02X%02X%02X shared",
465         di->pcii.vendor_id, di->pcii.device_id,
466         di->pcii.bus, di->pcii.device, di->pcii.function);
467     /* create this area with NO user-space read or write permissions, to prevent accidental dammage */
468     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,
469 		B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA);
470     if (di->sharedArea < 0) {
471         /* return the error */
472         result = di->sharedArea;
473         goto done;
474     }
475 
476     /* save a few dereferences */
477     si = di->si;
478 
479     /* save the vendor and device IDs */
480     si->vendor_id = di->pcii.vendor_id;
481     si->device_id = di->pcii.device_id;
482     si->revision = di->pcii.revision;
483 
484     si->pixelClockMax16 = 135000;
485     si->pixelClockMax24 = 135000;
486     if (si->vendor_id == 0x100C) { /* Tseng Labs, Inc. */
487         switch (si->device_id) {
488         case 0x3208:/* ET6000/ET6100 */
489             if (si->revision < 0x70) { /* ET6000 */
490                 si->pixelClockMax16 = 135000;
491                 si->pixelClockMax24 = 135000;
492             }
493             else { /* ET6100 */
494                 si->pixelClockMax16 = 175000;
495                 si->pixelClockMax24 = 175000;
496             }
497             break;
498         case 0x4702: /* ET6300 */
499             si->pixelClockMax16 = 220000;
500             si->pixelClockMax24 = 220000;
501             break;
502         }
503     }
504 
505     /* map the device */
506     result = et6000MapDevice(di);
507     if (result < 0)
508         goto free_shared;
509     result = B_OK;
510 
511     /*
512      * Clear any pending interrupts and disable interrupts. Driver
513      * currently does not use interrupts and unlikely will in future.
514      */
515     et6000aclReadInterruptClear(si->mmRegs);
516     et6000aclWriteInterruptClear(si->mmRegs);
517     et6000aclMasterInterruptDisable(si->mmRegs);
518 
519     /* Install the interrupt handler */
520     result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line,
521                                        et6000Interrupt, (void *)di, 0);
522     /* bail if we couldn't install the handler */
523     if (result != B_OK)
524         goto unmap;
525 
526 mark_as_open:
527     /* mark the device open */
528     di->isOpen++;
529 
530     /* send the cookie to the opener */
531     *cookie = di;
532 
533     goto done;
534 
535 unmap:
536     et6000UnmapDevice(di);
537 
538 free_shared:
539     /* clean up our shared area */
540     delete_area(di->sharedArea);
541     di->sharedArea = -1;
542     di->si = NULL;
543 
544 done:
545     /* end of critical section */
546     RELEASE_BEN(pd->kernel);
547 
548     /* all done, return the status */
549     ddprintf(("et6000OpenHook returning 0x%08lx\n", result));
550 
551     return result;
552 }
553 /*****************************************************************************/
554 /*
555  * et6000ReadHook - does nothing, gracefully
556  */
557 static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len)
558 {
559     *len = 0;
560     return B_NOT_ALLOWED;
561 }
562 
563 /*****************************************************************************/
564 /*
565  * et6000WriteHook - does nothing, gracefully
566  */
567 static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len)
568 {
569     *len = 0;
570     return B_NOT_ALLOWED;
571 }
572 /*****************************************************************************/
573 /*
574  * et6000CloseHook - does nothing, gracefully
575  */
576 static status_t et6000CloseHook(void* dev)
577 {
578     ddprintf(("SKD et6000CloseHook(%08lx)\n", (uint32)dev));
579     /* we don't do anything on close: there might be dup'd fd */
580     return B_NO_ERROR;
581 }
582 /*****************************************************************************/
583 /*
584  * et6000FreeHook - close down the device
585  */
586 static status_t et6000FreeHook(void* dev) {
587 ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev;
588 ET6000SharedInfo *si = di->si;
589 
590     ddprintf(("SKD et6000FreeHook() begins...\n"));
591     /* lock the driver */
592     AQUIRE_BEN(pd->kernel);
593 
594     /* if opened multiple times, decrement the open count and exit */
595     if (di->isOpen > 1)
596         goto unlock_and_exit;
597 
598     /* Clear any pending interrupts and disable interrupts. */
599     et6000aclReadInterruptClear(si->mmRegs);
600     et6000aclWriteInterruptClear(si->mmRegs);
601     et6000aclMasterInterruptDisable(si->mmRegs);
602 
603     /* Remove the interrupt handler */
604     remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, et6000Interrupt, di);
605 
606     /* free framebuffer area */
607     et6000UnmapDevice(di);
608 
609     /* clean up our shared area */
610     delete_area(di->sharedArea);
611     di->sharedArea = -1;
612     di->si = NULL;
613 
614 unlock_and_exit:
615     /* mark the device available */
616     di->isOpen--;
617     /* unlock the driver */
618     RELEASE_BEN(pd->kernel);
619     ddprintf(("SKD et6000FreeHook() ends.\n"));
620     /* all done */
621     return B_OK;
622 }
623 /*****************************************************************************/
624 /*
625  * et6000ControlHook - where the real work is done
626  */
627 static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len) {
628 ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev;
629 status_t result = B_DEV_INVALID_IOCTL;
630 
631     /* ddprintf(("ioctl: %d, buf: 0x%08x, len: %d\n", msg, buf, len)); */
632     switch (msg) {
633         /* the only PUBLIC ioctl */
634         case B_GET_ACCELERANT_SIGNATURE: {
635             char *sig = (char *)buf;
636             strcpy(sig, "et6000.accelerant");
637             result = B_OK;
638         } break;
639 
640         /* PRIVATE ioctl from here on */
641         case ET6000_GET_PRIVATE_DATA: {
642             ET6000GetPrivateData *gpd = (ET6000GetPrivateData *)buf;
643             if (gpd->magic == ET6000_PRIVATE_DATA_MAGIC) {
644                 gpd->sharedInfoArea = di->sharedArea;
645                 result = B_OK;
646             }
647         } break;
648 
649         case ET6000_GET_PCI: {
650             ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf;
651             if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) {
652                 pci_info *pcii = &(di->pcii);
653                 gsp->value = get_pci(gsp->offset, gsp->size);
654                 result = B_OK;
655             }
656         } break;
657 
658         case ET6000_SET_PCI: {
659             ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf;
660             if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) {
661                 pci_info *pcii = &(di->pcii);
662                 set_pci(gsp->offset, gsp->size, gsp->value);
663                 result = B_OK;
664             }
665         } break;
666 
667         case ET6000_DEVICE_NAME: {   /* Needed for cloning */
668             ET6000DeviceName *dn = (ET6000DeviceName *)buf;
669             if(dn->magic == ET6000_PRIVATE_DATA_MAGIC) {
670                 strncpy(dn->name, di->name, B_OS_NAME_LENGTH);
671                 result = B_OK;
672             }
673         } break;
674 
675         case ET6000_PROPOSE_DISPLAY_MODE: {
676             ET6000DisplayMode *dm = (ET6000DisplayMode *)buf;
677             if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) {
678                 result = et6000ProposeMode(&dm->mode, dm->memSize);
679             }
680         } break;
681 
682         case ET6000_SET_DISPLAY_MODE: {
683             ET6000DisplayMode *dm = (ET6000DisplayMode *)buf;
684             if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) {
685                 result = et6000SetMode(&dm->mode, dm->pciConfigSpace);
686             }
687         } break;
688     }
689     return result;
690 }
691 /*****************************************************************************/
692 #if DEBUG > 0
693 static int et6000dump(int argc, char **argv) {
694 int i;
695 
696     kprintf("ET6000 Kernel Driver Persistant Data\n\nThere are %ld card(s)\n", pd->count);
697     kprintf("Driver wide benahpore: %ld/%ld\n", pd->kernel.ben, pd->kernel.sem);
698 
699     kprintf("Total seen interrupts: %ld\n", pd->total_interrupts);
700     for (i = 0; i < pd->count; i++) {
701         ET6000DeviceInfo *di = &(pd->di[i]);
702         uint16 device_id = di->pcii.device_id;
703         ET6000SharedInfo *si = di->si;
704         kprintf("  device_id: 0x%04x\n", device_id);
705         kprintf("  interrupt count: %ld\n", di->interrupt_count);
706         if (si) {
707             kprintf("  flags:");
708         }
709         kprintf("\n");
710     }
711     return 1; /* the magic number for success */
712 }
713 #endif
714 /*****************************************************************************/
715