mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 10:04:12 +08:00
8736595bb2
Both onboard controller of the O2 support FAST-20 transfer speeds, but the bit, which signals that to the aic driver, isn't set. Instead of adding detection code to the scsi driver, we just fake the missing bit in the PCI config space of the scsi chips. Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
103 lines
2.3 KiB
C
103 lines
2.3 KiB
C
/*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* Copyright (C) 2000, 2001 Keith M Wesolowski
|
|
*/
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/types.h>
|
|
#include <asm/pci.h>
|
|
#include <asm/ip32/mace.h>
|
|
|
|
#if 0
|
|
# define DPRINTK(args...) printk(args);
|
|
#else
|
|
# define DPRINTK(args...)
|
|
#endif
|
|
|
|
/*
|
|
* O2 has up to 5 PCI devices connected into the MACE bridge. The device
|
|
* map looks like this:
|
|
*
|
|
* 0 aic7xxx 0
|
|
* 1 aic7xxx 1
|
|
* 2 expansion slot
|
|
* 3 N/C
|
|
* 4 N/C
|
|
*/
|
|
|
|
static inline int mkaddr(struct pci_bus *bus, unsigned int devfn,
|
|
unsigned int reg)
|
|
{
|
|
return ((bus->number & 0xff) << 16) |
|
|
((devfn & 0xff) << 8) |
|
|
(reg & 0xfc);
|
|
}
|
|
|
|
|
|
static int
|
|
mace_pci_read_config(struct pci_bus *bus, unsigned int devfn,
|
|
int reg, int size, u32 *val)
|
|
{
|
|
u32 control = mace->pci.control;
|
|
|
|
/* disable master aborts interrupts during config read */
|
|
mace->pci.control = control & ~MACEPCI_CONTROL_MAR_INT;
|
|
mace->pci.config_addr = mkaddr(bus, devfn, reg);
|
|
switch (size) {
|
|
case 1:
|
|
*val = mace->pci.config_data.b[(reg & 3) ^ 3];
|
|
break;
|
|
case 2:
|
|
*val = mace->pci.config_data.w[((reg >> 1) & 1) ^ 1];
|
|
break;
|
|
case 4:
|
|
*val = mace->pci.config_data.l;
|
|
break;
|
|
}
|
|
/* ack possible master abort */
|
|
mace->pci.error &= ~MACEPCI_ERROR_MASTER_ABORT;
|
|
mace->pci.control = control;
|
|
/*
|
|
* someone forgot to set the ultra bit for the onboard
|
|
* scsi chips; we fake it here
|
|
*/
|
|
if (bus->number == 0 && reg == 0x40 && size == 4 &&
|
|
(devfn == (1 << 3) || devfn == (2 << 3)))
|
|
*val |= 0x1000;
|
|
|
|
DPRINTK("read%d: reg=%08x,val=%02x\n", size * 8, reg, *val);
|
|
|
|
return PCIBIOS_SUCCESSFUL;
|
|
}
|
|
|
|
static int
|
|
mace_pci_write_config(struct pci_bus *bus, unsigned int devfn,
|
|
int reg, int size, u32 val)
|
|
{
|
|
mace->pci.config_addr = mkaddr(bus, devfn, reg);
|
|
switch (size) {
|
|
case 1:
|
|
mace->pci.config_data.b[(reg & 3) ^ 3] = val;
|
|
break;
|
|
case 2:
|
|
mace->pci.config_data.w[((reg >> 1) & 1) ^ 1] = val;
|
|
break;
|
|
case 4:
|
|
mace->pci.config_data.l = val;
|
|
break;
|
|
}
|
|
|
|
DPRINTK("write%d: reg=%08x,val=%02x\n", size * 8, reg, val);
|
|
|
|
return PCIBIOS_SUCCESSFUL;
|
|
}
|
|
|
|
struct pci_ops mace_pci_ops = {
|
|
.read = mace_pci_read_config,
|
|
.write = mace_pci_write_config,
|
|
};
|