patch-2.2.0-pre7 linux/arch/alpha/kernel/core_polaris.c
Next file: linux/arch/alpha/kernel/core_t2.c
Previous file: linux/arch/alpha/kernel/bios32.h
Back to the patch index
Back to the overall index
- Lines: 276
- Date:
Sun Jan 10 22:56:43 1999
- Orig file:
v2.2.0-pre6/linux/arch/alpha/kernel/core_polaris.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.2.0-pre6/linux/arch/alpha/kernel/core_polaris.c linux/arch/alpha/kernel/core_polaris.c
@@ -0,0 +1,275 @@
+/*
+ * linux/arch/alpha/kernel/core_polaris.c
+ *
+ * POLARIS chip-specific code
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/pci.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_polaris.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+#include "bios32.h"
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG_CONFIG
+# define DBG_CFG(args) printk args
+#else
+# define DBG_CFG(args)
+#endif
+
+#define DEBUG_MCHECK
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args) printk args
+/* #define DEBUG_MCHECK_DUMP */
+#else
+# define DBG_MCK(args)
+#endif
+
+static volatile unsigned int POLARIS_mcheck_expected = 0;
+static volatile unsigned int POLARIS_mcheck_taken = 0;
+static volatile unsigned short POLARIS_jd = 0;
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address. This is fairly straightforward
+ * on POLARIS, since the chip itself generates Type 0 or Type 1
+ * cycles automatically depending on the bus number (Bus 0 is
+ * hardwired to Type 0, all others are Type 1. Peer bridges
+ * are not supported).
+ *
+ * All types:
+ *
+ * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1|1|1|1|1|0|0|1|1|1|1|1|1|1|1|0|B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|x|x|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ * Notes:
+ * The function number selects which function of a multi-function device
+ * (e.g., scsi and ethernet).
+ *
+ * The register selects a DWORD (32 bit) register offset. Hence it
+ * doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ * bits.
+ */
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1)
+{
+ *type1 = (bus == 0) ? 0 : 1;
+ *pci_addr = (bus << 16) | (device_fn << 8) | (where) |
+ POLARIS_DENSE_CONFIG_BASE;
+
+ DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+ " returning address 0x%p\n"
+ bus, device_fn, where, *pci_addr));
+
+ return 0;
+}
+
+int
+polaris_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldbu(*(vucp)pci_addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+polaris_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldwu(*(vusp)pci_addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+polaris_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = *(vuip)pci_addr;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stb(value, *(vucp)pci_addr);
+ mb();
+ __kernel_ldbu(*(vucp)pci_addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stw(value, *(vusp)pci_addr);
+ mb();
+ __kernel_ldbu(*(vusp)pci_addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int
+polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *(vuip)pci_addr = value;
+ mb();
+ *(vuip)pci_addr;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ /* May need to initialize error reporting (see PCICTL0/1), but
+ * for now assume that the firmware has done the right thing
+ * already.
+ */
+#if 0
+ printk("polaris_init_arch(): trusting firmware for setup\n");
+#endif
+}
+
+int polaris_pci_clr_err(void)
+{
+ POLARIS_jd = *((vusp)POLARIS_W_STATUS);
+ DBG_MCK(("POLARIS_pci_clr_err: POLARIS_W_STATUS after read 0x%x\n",
+ POLARIS_jd));
+ /* Write 1's to settable bits to clear errors */
+ *((vusp)POLARIS_W_STATUS) = 0x7800; mb();
+ POLARIS_jd = *((vusp)POLARIS_W_STATUS);
+ return 0;
+}
+
+void polaris_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ struct el_common *mchk_header;
+ struct el_POLARIS_sysdata_mcheck *mchk_sysdata;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_sysdata =
+ (struct el_POLARIS_sysdata_mcheck *)(la_ptr+mchk_header->sys_offset);
+
+#if 0
+ DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset));
+ DBG_MCK(("polaris_machine_check: expected %d status 0x%lx\n",
+ POLARIS_mcheck_expected, mchk_sysdata->psc_status));
+#endif
+#ifdef DEBUG_MCHECK_DUMP
+ {
+ unsigned long *ptr;
+ int i;
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+ }
+#endif /* DEBUG_MCHECK_DUMP */
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb();
+ if (POLARIS_mcheck_expected) {
+ DBG_MCK(("POLARIS machine check expected\n"));
+ POLARIS_mcheck_expected = 0;
+ POLARIS_mcheck_taken = 1;
+ mb();
+ mb();
+ draina();
+ polaris_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#if 1
+ else {
+ printk("POLARIS machine check NOT expected\n") ;
+ DBG_MCK(("polaris_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset));
+ POLARIS_mcheck_expected = 0;
+ POLARIS_mcheck_taken = 1;
+ mb();
+ mb();
+ draina();
+ polaris_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#endif
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov