finalized MMS (multihead) card support. Fixed system crashing with null pointer if 'secondary' mms card in system was used on it's non-primary heads while it's primary head was not in use. (hope this is readable :). In other words: rewrote copying ROMs for MMS cards. Kerneldriver now holds images for each card and head inside the kerneldriver independant of a card's driver being actually used or not. multihead cards can now be used as you wish: they nolonger need to be the 'primary' card in your system. hehe: 6 heads running here (two on a dualhead nvidia while 4 in a matrox mms. Test harness much in use, as all those cards still can't be used otherwise on BeOS.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15211 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen
2005-11-29 10:40:55 +00:00
parent a6e6b1d36f
commit 9528941458
2 changed files with 65 additions and 3 deletions
@@ -4,7 +4,7 @@
</head>
<body>
<p><h2>Changes done for each driverversion:</h2></p>
<p><h1>head (SVN 0.25, Rudolf)</h1></p>
<p><h1>head (SVN 0.26, Rudolf)</h1></p>
<ul>
<li><strong>G200-G550:</strong>
<ul>
@@ -58,6 +58,7 @@ struct device_info {
vuint32 *regs; /* kernel's pointer to memory mapped registers */
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 */
uint8 rom_mirror[32768]; /* mirror of the ROM (is needed for MMS cards) */
};
typedef struct {
@@ -76,6 +77,7 @@ static status_t write_hook (void* dev, off_t pos, const void* buf, size_t* len);
static status_t control_hook (void* dev, uint32 msg, void *buf, size_t len);
static status_t map_device(device_info *di);
static void unmap_device(device_info *di);
static void copy_rom(device_info *di);
static void probe_devices(void);
static int32 gx00_interrupt(void *data);
@@ -416,8 +418,8 @@ static status_t map_device(device_info *di)
}
if (found)
{
/* make the copy from the primary VGA card */
memcpy (si->rom_mirror, pd->di[index].si->rom_mirror, 32768);
/* make the copy from the primary VGA card on our bus */
memcpy (si->rom_mirror, pd->di[index].rom_mirror, 32768);
}
else
{
@@ -569,6 +571,62 @@ static void unmap_device(device_info *di) {
di->regs = NULL;
}
static void copy_rom(device_info *di)
{
char buffer[B_OS_NAME_LENGTH];
uint8 *rom_temp;
area_id rom_area;
uint32 tmpUlong;
pci_info *pcii = &(di->pcii);
/* MIL1 has frame_buffer in [1], while MIL2 and later have frame_buffer in [0] */
int frame_buffer = 0;
/* correct layout for MIL1 */
//fixme: checkout Mystique 170 and 220...
if (di->pcii.device_id == 0x0519) frame_buffer = 1;
/* enable memory mapped IO, disable VGA I/O - this is standard*/
tmpUlong = get_pci(PCI_command, 4);
tmpUlong |= 0x00000002;
tmpUlong &= 0xfffffffe;
set_pci(PCI_command, 4, tmpUlong);
/* work out a name for the ROM mapping*/
sprintf(buffer, DEVICE_FORMAT " rom",
di->pcii.vendor_id, di->pcii.device_id,
di->pcii.bus, di->pcii.device, di->pcii.function);
/*place ROM over the fbspace (this is definately safe)*/
tmpUlong = di->pcii.u.h0.base_registers[frame_buffer];
tmpUlong |= 0x00000001;
set_pci(PCI_rom_base, 4, tmpUlong);
rom_area = map_physical_memory(
buffer,
(void *)di->pcii.u.h0.base_registers[frame_buffer],
32768,
B_ANY_KERNEL_ADDRESS,
B_READ_AREA,
(void **)&(rom_temp)
);
/* if mapping ROM to vmem was successfull copy it */
if (rom_area >= 0)
{
/* copy ROM for future reference (MMS cards) */
memcpy (di->rom_mirror, rom_temp, 32768);
/* disable ROM and delete the area */
set_pci(PCI_rom_base, 4, 0);
delete_area(rom_area);
}
/* disable memory mapped IO */
tmpUlong = get_pci(PCI_command, 4);
tmpUlong &= 0xfffffffc;
set_pci(PCI_command, 4, tmpUlong);
}
static void probe_devices(void)
{
uint32 pci_index = 0;
@@ -612,6 +670,10 @@ static void probe_devices(void)
di->shared_area = -1;
/* mark pointer to shared data as invalid */
di->si = NULL;
/* copy ROM for MMS (multihead with multiple GPU) cards:
* they might only have a ROM on the primary adaptor.
* (Confirmed G200MMS.) */
copy_rom(di);
/* inc pointer to device info */
di++;
/* inc count */