2003-02-04 22:25:55

by Rusty Lynch

[permalink] [raw]
Subject: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

Last week I finally got access to a decent (but old) technical specification
for the ZT5550 redundant host controller. The document was published for
the ZT5550C, but I am hoping that newer versions of the RHC just add more
functionality to all the documented reserved bits in the document I am looking
at.

The following patch adds a sysfs interface to most of the bits accessible
via the indirect register (through the HCINDEX and HCDATA addresses in the
Command and Status Register (CSR). The only bits I did not add access to
were the ones that are cleared by reading. There are a lot of bits to get
access to, which makes this patch a little bigger then I first expected,
so I created a new config option so only people who actually want to mess
with the RHC would pay for it.

Enabling this code will cause a new directory called zt5550_rhc to be
created in the root of sysfs, with the following tree:

[rusty@penguin sysfs]$ tree zt5550_rhc
zt5550_rhc/
|-- diag <== fault injection capabilities
| |-- diag_b0_serr
| |-- diag_cputemp
| |-- diag_iochk
| |-- diag_nmi
| |-- diag_perr
| |-- diag_power_fail
| `-- diag_wd_timeout
|-- fltc <== configurable actions for given faults
| |-- b0_serr
| |-- cputemp
| |-- eject_ah
| |-- eject_bh
| |-- hard_reset
| |-- iochk
| |-- nmi
| |-- perr
| |-- power_fail
| |-- soft_reset
| `-- wd_timeout
|-- hcc <== various commands
| |-- ah_s1_response
| |-- bh_s1_response
| |-- configuration_mode
| |-- diagnostics_mode
| |-- initiate_takeover
| |-- power_down_bh
| |-- reset
| |-- reset_bh
| |-- s1_bp_reset
| |-- s2_bp_reset
| |-- warm_boot
| `-- wd_enable
|-- hci <== interrupt mask settings
| |-- fault_interrupt_mask
| |-- hcf_interrupt_mask
| `-- serial_interrupt_mask
|-- isoc <== isolation configuration
| |-- bp_interrupt_mask
| |-- friendly
| |-- hostile
| |-- s1_bp_reset_mask
| |-- s2_bp_reset_mask
| `-- unlock
|-- pmcc <== control of PCI Mezzanine Cards
| |-- pmc1_command2
| |-- pmc1_command4
| |-- pmc1_status
| |-- pmc2_command2
| |-- pmc2_command4
| `-- pmc2_status
`-- wdc <== watchdog timer configuration
|-- prescaler
`-- terminal_count

This provides all kind of rope to hang yourself with, but it was
fun messing with it. This also points out other areas where an interested
party could further enable this particular board, for example adding the
code to respond to a fault condition (after enabling fault handling
through sysfs).

This patch was generated off of today's bk tree with the previously posted
patch by Scott to fix the deadlock issue and the patch posted by Stanley
to add sysfs support. Both of these patches are attached as a single
patch to this email message.

--rustyl

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.982 -> 1.983
# drivers/hotplug/cpcihp_zt5550.h 1.2 -> 1.3
# drivers/hotplug/Kconfig 1.5 -> 1.6
# drivers/hotplug/cpcihp_zt5550.c 1.2 -> 1.3
# drivers/hotplug/Makefile 1.12 -> 1.13
# (new) -> 1.1 drivers/hotplug/cpcihp_zt5550_rhc.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/04 [email protected] 1.983
# Adding a sysfs inteface for the zt5550 redundant host controller
# --------------------------------------------
#
diff -Nru a/drivers/hotplug/Kconfig b/drivers/hotplug/Kconfig
--- a/drivers/hotplug/Kconfig Tue Feb 4 13:50:01 2003
+++ b/drivers/hotplug/Kconfig Tue Feb 4 13:50:01 2003
@@ -101,6 +101,23 @@

When in doubt, say N.

+config HOTPLUG_PCI_CPCI_ZT5550_RHC
+ bool "Ziatech ZT5550 CompactPCI RHC Sysfs Interface"
+ depends on HOTPLUG_PCI_CPCI_ZT5550
+ help
+ Say Y here if you have an Performance Technologies (formerly Intel,
+ formerly just Ziatech) Ziatech ZT5550 CompactPCI system card, and
+ would like to have configuration access to the onboard
+ Redundant Host Controller.
+
+ Saying Y here will cause a new "zt5550_rhc" directory to be created
+ in the root of your sysfs, with a directory for each of the rhc
+ indirect registers created inside the zt5550_rhc directory, and then
+ control files in each of those directorys giving user space access
+ to all of the bits in those indirect registers.
+
+ When in doubt, say N.
+
config HOTPLUG_PCI_CPCI_GENERIC
tristate "Generic port I/O CompactPCI Hotplug driver"
depends on HOTPLUG_PCI_CPCI && X86
diff -Nru a/drivers/hotplug/Makefile b/drivers/hotplug/Makefile
--- a/drivers/hotplug/Makefile Tue Feb 4 13:50:01 2003
+++ b/drivers/hotplug/Makefile Tue Feb 4 13:50:01 2003
@@ -7,6 +7,7 @@
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
+obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC) += cpcihp_zt5550_rhc.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o

pci_hotplug-objs := pci_hotplug_core.o \
diff -Nru a/drivers/hotplug/cpcihp_zt5550.c b/drivers/hotplug/cpcihp_zt5550.c
--- a/drivers/hotplug/cpcihp_zt5550.c Tue Feb 4 13:50:01 2003
+++ b/drivers/hotplug/cpcihp_zt5550.c Tue Feb 4 13:50:01 2003
@@ -35,6 +35,8 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/kobject.h>
+#include <linux/bitops.h>
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"

@@ -42,22 +44,6 @@
#define DRIVER_AUTHOR "Scott Murray <[email protected]>"
#define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver"

-#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
-#define MY_NAME "cpcihp_zt5550"
-#else
-#define MY_NAME THIS_MODULE->name
-#endif
-
-#define dbg(format, arg...) \
- do { \
- if(debug) \
- printk (KERN_DEBUG "%s: " format "\n", \
- MY_NAME , ## arg); \
- } while(0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
-
/* local variables */
static int debug;
static int poll;
@@ -75,8 +61,8 @@

/* Host controller register addresses */
static void *hc_registers;
-static void *csr_hc_index;
-static void *csr_hc_data;
+void *csr_hc_index;
+void *csr_hc_data;
static void *csr_intstat;
static void *csr_intmask;

@@ -259,12 +245,12 @@
}
dbg("registered controller");

- if(hcf_hcs & HCS_BUS1_ACTIVE) {
+ if(hcf_hcs & HCS_BUS1_ACTIVE_MASK) {
status = zt5550_register_bus(BUS1_SLOT, &bus1_dev, &bus1);
if(status)
goto init_register_error;
}
- if(hcf_hcs & HCS_BUS2_ACTIVE) {
+ if(hcf_hcs & HCS_BUS2_ACTIVE_MASK) {
status = zt5550_register_bus(BUS2_SLOT, &bus2_dev, &bus2);
if(status)
goto init_register_error;
@@ -318,13 +304,20 @@

static int __init zt5550_init(void)
{
+ int rv;
+
info(DRIVER_DESC " version: " DRIVER_VERSION);
- return pci_module_init(&zt5550_hc_driver);
+ rv = pci_module_init(&zt5550_hc_driver);
+ if (!rv)
+ create_hc_files(csr_hc_index,csr_hc_data);
+
+ return rv;
}

static void __exit
zt5550_exit(void)
{
+ remove_hc_files();
pci_unregister_driver(&zt5550_hc_driver);
release_region(ENUM_PORT, 1);
}
diff -Nru a/drivers/hotplug/cpcihp_zt5550.h b/drivers/hotplug/cpcihp_zt5550.h
--- a/drivers/hotplug/cpcihp_zt5550.h Tue Feb 4 13:50:01 2003
+++ b/drivers/hotplug/cpcihp_zt5550.h Tue Feb 4 13:50:01 2003
@@ -33,6 +33,22 @@
#ifndef _CPCIHP_ZT5550_H
#define _CPCIHP_ZT5550_H

+#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
+#define MY_NAME "cpcihp_zt5550"
+#else
+#define MY_NAME THIS_MODULE->name
+#endif
+
+#define dbg(format, arg...) \
+ do { \
+ if(debug) \
+ printk (KERN_DEBUG "%s: " format "\n", \
+ MY_NAME , ## arg); \
+ } while(0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
+
/* Direct registers */
#define CSR_HCINDEX 0x00
#define CSR_HCDATA 0x04
@@ -44,12 +60,40 @@
#define CSR_TIM0 0x10
#define CSR_TIM1 0x14

+/* Masks for bits in CSR_INTSTAT (interrupt status) direct register */
+#define INTSTAT_SERIAL_FLAG 0x01
+#define INTSTAT_FAULT_FLAG 0x02
+#define INTSTAT_HCS_FLAG 0x04
+#define INTSTAT_TIM0_FLAG 0x08
+#define INTSTAT_TIM1_FLAG 0x10
+#define INTSTAT_ENUM_FLAG 0x20
+
/* Masks for interrupt bits in CSR_INTMASK direct register */
#define INTMASK_TIM0_INT_MASK 0x01
#define INTMASK_TIM1_INT_MASK 0x02
#define INTMASK_ENUM_INT_MASK 0x04
#define INTMASK_ALL_INTS_MASK 0x07

+/* Mask for bits in CSR_ENET (ethernet routing) direct register */
+#define ENET_A_REAR 0x01
+#define ENET_B_ROUTING 0x60
+
+/* Mask for bits in the CSR_T0_C (timer #0 control) direct register */
+#define T0_C_ENABLE 0x0001
+#define T0_C_TIMEOUT_MODE 0x0002
+#define T0_C_CLOCK_SOURCE 0x000c
+#define T0_C_READ_MODE 0x0030
+#define T0_C_WRITE_MODE 0x0040
+#define T0_C_OUTPUT_FLAG 0x0080
+
+/* Mask for bits in the CSR_T1_C (timer #1 control) direct register */
+#define T1_C_ENABLE 0x0001
+#define T1_C_TIMEOUT_MODE 0x0002
+#define T1_C_CLOCK_SOURCE 0x000c
+#define T1_C_READ_MODE 0x0030
+#define T1_C_WRITE_MODE 0x0040
+#define T1_C_OUTPUT_FLAG 0x0080
+
/* Indexed registers (through CSR_HCINDEX, CSR_HCDATA) */
#define HCF_HCI 0x04
#define HCF_HCS 0x08
@@ -65,32 +109,233 @@
#define HCF_SDO 0x38
#define HCF_SDI 0x3C

-/* Masks for interrupt bits in HCF_HCI indexed register */
+/* Masks for interrupt bits in HCF_HCI */
+/* (host controller interrupt) indexed register */
#define HCI_SERIAL_INT_MASK 0x01
#define HCI_FAULT_INT_MASK 0x02
#define HCI_HCF_INT_MASK 0x04
#define HCI_ALL_INTS_MASK 0x07

-/* Masks for the bits in the HCF_HCS indexed register */
-#define HCS_HA 0x00000001
-#define HCS_ACTIVE 0x00000002
-#define HCS_RH_STATE 0x00000004
-#define HCS_HARD_RESET 0x00000008
-#define HCS_SOFT_RESET 0x00000010
-#define HCS_RH_ALIVE 0x00000020
-#define HCS_SWITCH_OVER 0x00000040
-#define HCS_TAKEOVER_TYPE 0x00000080
-#define HCS_BUS1_ACTIVE 0x00000100
-#define HCS_BUS2_ACTIVE 0x00000200
-#define HCS_SPLIT_MODE_ERROR 0x00000400
+/* Masks for the bits in the HCF_HCS */
+/* (host controller status) indexed register */
+#define HCS_HA_MASK 0x00000001
+#define HCS_ACTIVE_MASK 0x00000002
+#define HCS_RH_STATE_MASK 0x00000004
+#define HCS_HARD_RESET_MASK 0x00000008
+#define HCS_SOFT_RESET_MASK 0x00000010
+#define HCS_RH_ALIVE_MASK 0x00000020
+#define HCS_SWITCH_OVER_MASK 0x00000040
+#define HCS_TAKEOVER_TYPE_MASK 0x00000080
+#define HCS_BUS1_ACTIVE_MASK 0x00000100
+#define HCS_BUS2_ACTIVE_MASK 0x00000200
+#define HCS_SPLIT_MODE_ERR_MASK 0x00000400
+
+/* Masks for the bits in the HCF_HCC */
+/* (host controller command) indexed register */
+#define HCC_RESET_MASK 0x00000001
+#define HCC_DIAG_MODE_MASK 0x00000002
+#define HCC_CONFIG_MODE_MASK 0x00000004
+#define HCC_S2_BP_RESET_MASK 0x00000008
+#define HCC_S1_BP_RESET_MASK 0x00000010
+#define HCC_WARM_BOOT_MASK 0x00000020
+#define HCC_INIT_TAKEOVER_MASK 0x00000040
+#define HCC_WD_ENABLE_MASK 0x00000080
+#define HCC_RESET_BH_MASK 0x00000100
+#define HCC_POWER_DOWN_BH_MASK 0x00000200
+#define HCC_BH_S1_RESPONSE_MASK 0x00001000
+#define HCC_AH_S1_RESPONSE_MASK 0x00002000
+
+/* Masks for the bits in the HCF_ARBC */
+/* (arbitration configuration) indexed register */
+#define ARBC_S1_GNT0_MASK 0x00000001
+#define ARBC_S1_GNT1_MASK 0x00000002
+#define ARBC_S1_GNT2_MASK 0x00000004
+#define ARBC_S1_GNT3_MASK 0x00000008
+#define ARBC_S1_GNT4_MASK 0x00000010
+#define ARBC_S1_GNT5_MASK 0x00000020
+#define ARBC_S1_GNT6_MASK 0x00000040
+#define ARBC_S1_GNT7_MASK 0x00000080
+#define ARBC_S2_GNT0_MASK 0x00000100
+#define ARBC_S2_GNT1_MASK 0x00000200
+#define ARBC_S2_GNT2_MASK 0x00000400
+#define ARBC_S2_GNT3_MASK 0x00000800
+#define ARBC_S2_GNT4_MASK 0x00001000
+#define ARBC_S2_GNT5_MASK 0x00002000
+#define ARBC_S2_GNT6_MASK 0x00004000
+#define ARBC_S2_GNT7_MASK 0x00008000
+
+/* Masks for the bits in the HCF_ISOC */
+/* (isolation configuration) indexed register */
+#define ISOC_UNLOCK_MASK 0x00000001
+#define ISOC_S1_BP_RESET_MASK 0x00000002
+#define ISOC_S2_BP_RESET_MASK 0x00000004
+#define ISOC_BP_INTERRUPT_MASK 0x00000008
+#define ISOC_HOSTILE_MASK 0x00000030
+#define ISOC_FRIENDLY_MASK 0x000000c0
+
+/* Masks for the bits in the HCF_FLTS (fault status) indexed register */
+#define FLTS_WD_TIMEOUT_MASK 0x00000001
+#define FLTS_PERR_MASK 0x00000002
+#define FLTS_IOCHK_MASK 0x00000004
+#define FLTS_NMI_MASK 0x00000008
+#define FLTS_B0_SERR_MASK 0x00000010
+#define FLTS_CPUTEMP_MASK 0x00000040
+#define FLTS_POWER_FAIL_MASK 0x00000080
+#define FLTS_EJECT_BH_MASK 0x00000100
+#define FLTS_EJECT_AH_MASK 0x00000200
+
+/* Masks for the bits in the HCF_FLTC (fault configuration) indexed register */
+#define FLTC_WD_TIMEOUT_MASK 0x00000007
+#define FLTC_PERR_MASK 0x00000038
+#define FLTC_IOCHK_MASK 0x000001c0
+#define FLTC_NMI_MASK 0x00000e00
+#define FLTC_B0_SERR_MASK 0x00007000
+#define FLTC_CPUTEMP_MASK 0x001c0000
+#define FLTC_POWER_FAIL_MASK 0x00e00000
+#define FLTC_EJECT_BH_MASK 0x07000000
+#define FLTC_EJECT_AH_MASK 0x38000000
+#define FLTC_SOFT_RESET_MASK 0x40000000
+#define FLTC_HARD_RESET_MASK 0x80000000
+
+/* Masks for the bits in the HCF_PMCC (PMC control) indexed register */
+#define PMCC_PMC1_STATUS_MASK 0x00000001
+#define PMCC_PMC1_COMMAND2_MASK 0x00000002
+#define PMCC_PMC1_COMMAND4_MASK 0x00000004
+#define PMCC_PMC2_STATUS_MASK 0x00000010
+#define PMCC_PMC2_COMMAND2_MASK 0x00000020
+#define PMCC_PMC2_COMMAND4_MASK 0x00000040
+
+/* Masks for the bits in the HCF_WDC (watchdog control) indexed register */
+#define WDC_TERMINAL_COUNT_MASK 0x0000003f
+#define WDC_PRESCALER_MASK 0x000000c0
+
+/* Masks for the bits in the HCF_DIAG (diagnostics command) indexed register */
+#define DIAG_WD_TIMEOUT_MASK 0x00000001
+#define DIAG_PERR_MASK 0x00000002
+#define DIAG_IOCHK_MASK 0x00000004
+#define DIAG_NMI_MASK 0x00000008
+#define DIAG_B0_SERR_MASK 0x00000010
+#define DIAG_CPUTEMP_MASK 0x00000040
+#define DIAG_POWER_FAIL_MASK 0x00000080
+
+/* Masks for the bits in the HCF_SERC (diagnostics command) indexed register */
+#define SERC_DATA_SENT 0x00000001
+#define SERC_DATA_RECIEVED 0x00000002
+#define SERC_SDO_FLAG_ENABLE 0x00000004
+#define SERC_SDI_FLAG_ENABLE 0x00000008
+#define SERC_HCSI_OFF 0x00000010
+#define SERC_FIND_TOKEN 0x00000020

/* CompactPCI bus segment device slot numbers */
#define BUS1_SLOT 0x08
#define BUS2_SLOT 0x0C

+/* I/O port for setting and configuring watchdog timer */
+#define WDT_PORT 0x79
+
+/* Masks for bits written/read from the watchdog timer port */
+#define WDT_TERMINAL_COUNT 0x07
+#define WDT_FIRST_STAGE_ENABLE 0x10
+#define WDT_RESET_ENABLE 0x20
+#define WDT_FIRST_STAGE_MONITOR 0x40
+#define WDT_RESET_MONITOR 0x80
+
/* Digital I/O port storing ENUM# */
#define ENUM_PORT 0xE1
/* Mask to get to the ENUM# bit on the bus */
#define ENUM_MASK 0x40

+#define hcf_read(index, value, csr_hc_index, csr_hc_data) \
+ { \
+ writeb((u8) index, csr_hc_index); \
+ value = readl(csr_hc_data); \
+ dbg("hcf_read(0x%08x, 0x%08x)",index,value); \
+ }
+
+#define hcf_write(index, value, csr_hc_index, csr_hc_data) \
+ { \
+ writeb((u8) index, csr_hc_index); \
+ writel(value, csr_hc_data); \
+ dbg("hcf_write(0x%08x, 0x%08x)",index,value); \
+ }
+
+#define hcf_set_bit(index, bit, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ hcf_write(index, tmp|bit, csr_hc_index, csr_hc_data); \
+ dbg("hcf_set_bit(0x%08x, 0x%08x)",index,bit); \
+ }
+
+#define hcf_clear_bit(index, bit, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ hcf_write(index, tmp & ~bit, csr_hc_index, csr_hc_data); \
+ dbg("hcf_clear_bit(0x%08x, 0x%08x)",index,bit); \
+ }
+
+#define hcf_write_bits(index, mask, request, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ dbg("hcf_write_bits(0x%08x, 0x%08x, 0x%08x)", \
+ index,mask,request); \
+ request = request << (generic_ffs(mask) - 1); \
+ request &= mask; \
+ request |= ~mask; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ tmp |= mask; \
+ tmp &= request; \
+ hcf_write(index, tmp, csr_hc_index, csr_hc_data); \
+ }
+
+#define hcf_read_bits(index, mask, value, csr_hc_index, csr_hc_data) \
+ { \
+ hcf_read(index, value, csr_hc_index, csr_hc_data); \
+ value = (mask&value)>>(generic_ffs(mask) - 1); \
+ dbg("hcf_read_bits(0x%08x, 0x%08x, 0x%08x)", \
+ index,mask,value); \
+ }
+
+#define decl_hc_attribute(_name) \
+static struct rhc_attribute _name##_attr = { \
+ .attr = { .name = __stringify(_name), .mode = 0644 }, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+}
+
+#define decl_hc_kobject(_name) \
+static struct rhc _name##_obj = { \
+ .kobj.name = __stringify(_name), \
+}
+
+
+#define decl_hc_show_function(_name, _index, _mask) \
+static ssize_t _name##_show(struct rhc * p, char * page) \
+{ \
+ int tmp; \
+ hcf_read_bits(_index, _mask, tmp, p->index, p->data); \
+ return sprintf(page,"%d\n", tmp); \
+}
+
+#define decl_hc_store_function(_name, _index, _mask) \
+static ssize_t _name##_store(struct rhc * p, const char * page, size_t count) \
+{ \
+ int request; \
+ if (sscanf(page, "%i", &request)) {\
+ hcf_write_bits(_index, _mask, request, p->index, p->data); \
+ return count; \
+ } \
+ return -EINVAL; \
+}
+
+#ifdef CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC
+extern void create_hc_files(void *index,void *data);
+extern void remove_hc_files(void);
+#else /* !CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC */
+static inline void create_hc_files(void *index,void *data){}
+static inline void remove_hc_files(void){}
+#endif
+
#endif /* _CPCIHP_ZT5550_H */
+
diff -Nru a/drivers/hotplug/cpcihp_zt5550_rhc.c b/drivers/hotplug/cpcihp_zt5550_rhc.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/hotplug/cpcihp_zt5550_rhc.c Tue Feb 4 13:50:01 2003
@@ -0,0 +1,538 @@
+/*
+ * cpcihp_zt5550.c
+ *
+ * Intel/Ziatech ZT5550 CompactPCI Redundant Host Controller Sysfs Interface
+ *
+ * Copyright 2002 SOMA Networks, Inc.
+ * Copyright 2001 Intel San Luis Obispo
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/kobject.h>
+#include <linux/bitops.h>
+#include "cpci_hotplug.h"
+#include "cpcihp_zt5550.h"
+
+extern int debug;
+extern void *csr_hc_index;
+extern void *csr_hc_data;
+
+struct rhc {
+ void *index;
+ void *data;
+ struct kobject kobj;
+};
+struct rhc_attribute {
+ struct attribute attr;
+ ssize_t (*show) (struct rhc *,char *);
+ ssize_t (*store)(struct rhc *,const char *, size_t);
+};
+
+static ssize_t rhc_attr_show(struct kobject * kobj,
+ struct attribute * attr,
+ char * page)
+{
+ struct rhc * i = container_of(kobj,struct rhc,kobj);
+ struct rhc_attribute * rhc_attr =
+ container_of(attr,struct rhc_attribute,attr);
+
+ return rhc_attr->show ? rhc_attr->show(i,page) : 0;
+}
+
+static ssize_t rhc_attr_store(struct kobject * kobj,
+ struct attribute * attr,
+ const char * page,
+ size_t count)
+{
+ struct rhc * i = container_of(kobj,struct rhc,kobj);
+ struct rhc_attribute * rhc_attr =
+ container_of(attr,struct rhc_attribute,attr);
+
+ return rhc_attr->store ? rhc_attr->store(i,page,count) : 0;
+}
+
+static struct sysfs_ops rhc_sysfs_ops = {
+ .show = rhc_attr_show,
+ .store = rhc_attr_store,
+};
+
+static struct kobj_type rhc_ktype = {
+ .sysfs_ops = &rhc_sysfs_ops
+};
+
+static struct subsystem rhc_subsys = {
+ .kset = {
+ .kobj = { .name = "zt5550_rhc" },
+ .ktype = &rhc_ktype,
+ }
+};
+
+/**********************************************************************
+ * Host Control Interrupt register attributes
+ */
+decl_hc_kobject(hci);
+
+/* Host Control Function Interrupt Mask */
+decl_hc_store_function(hcf_interrupt_mask,HCF_HCI,HCI_HCF_INT_MASK);
+decl_hc_show_function(hcf_interrupt_mask,HCF_HCI,HCI_HCF_INT_MASK);
+decl_hc_attribute(hcf_interrupt_mask);
+
+/* Fault Interrupt Mask */
+decl_hc_store_function(fault_interrupt_mask,HCF_HCI,HCI_FAULT_INT_MASK);
+decl_hc_show_function(fault_interrupt_mask,HCF_HCI,HCI_FAULT_INT_MASK);
+decl_hc_attribute(fault_interrupt_mask);
+
+/* Serial Communications Interrupt Mask */
+decl_hc_store_function(serial_interrupt_mask,HCF_HCI,HCI_SERIAL_INT_MASK);
+decl_hc_show_function(serial_interrupt_mask,HCF_HCI,HCI_SERIAL_INT_MASK);
+decl_hc_attribute(serial_interrupt_mask);
+
+/**********************************************************************
+ * Host Control Command attributes
+ * NOTE: The HCC register is by default locked. To change any
+ * value, first unlock by writing a '1' to the UNLOCK bit
+ * in the ISOC register.
+ */
+decl_hc_kobject(hcc);
+
+/* Reset Command */
+decl_hc_store_function(reset,HCF_HCC,HCC_RESET_MASK);
+decl_hc_show_function(reset,HCF_HCC,HCC_RESET_MASK);
+decl_hc_attribute(reset);
+
+/* Diagnostics Mode Command */
+decl_hc_store_function(diagnostics_mode,HCF_HCC,HCC_DIAG_MODE_MASK);
+decl_hc_show_function(diagnostics_mode,HCF_HCC,HCC_DIAG_MODE_MASK);
+decl_hc_attribute(diagnostics_mode);
+
+/* Configuration Mode Command */
+decl_hc_store_function(configuration_mode,HCF_HCC,HCC_CONFIG_MODE_MASK);
+decl_hc_show_function(configuration_mode,HCF_HCC,HCC_CONFIG_MODE_MASK);
+decl_hc_attribute(configuration_mode);
+
+/* S1 Backplane Reset Command */
+decl_hc_store_function(s1_bp_reset,HCF_HCC,HCC_S1_BP_RESET_MASK);
+decl_hc_show_function(s1_bp_reset,HCF_HCC,HCC_S1_BP_RESET_MASK);
+decl_hc_attribute(s1_bp_reset);
+
+/* S2 Backplane Reset Command */
+decl_hc_store_function(s2_bp_reset,HCF_HCC,HCC_S2_BP_RESET_MASK);
+decl_hc_show_function(s2_bp_reset,HCF_HCC,HCC_S2_BP_RESET_MASK);
+decl_hc_attribute(s2_bp_reset);
+
+/* Warm Boot Flag */
+decl_hc_store_function(warm_boot,HCF_HCC,HCC_WARM_BOOT_MASK);
+decl_hc_show_function(warm_boot,HCF_HCC,HCC_WARM_BOOT_MASK);
+decl_hc_attribute(warm_boot);
+
+/* Initiate Takeover Command */
+decl_hc_store_function(initiate_takeover,HCF_HCC,HCC_INIT_TAKEOVER_MASK);
+decl_hc_show_function(initiate_takeover,HCF_HCC,HCC_INIT_TAKEOVER_MASK);
+decl_hc_attribute(initiate_takeover);
+
+/* Watchdog Enable Command */
+decl_hc_store_function(wd_enable,HCF_HCC,HCC_WD_ENABLE_MASK);
+decl_hc_show_function(wd_enable,HCF_HCC,HCC_WD_ENABLE_MASK);
+decl_hc_attribute(wd_enable);
+
+/* Reset Backup Host Command*/
+decl_hc_store_function(reset_bh,HCF_HCC,HCC_RESET_BH_MASK);
+decl_hc_show_function(reset_bh,HCF_HCC,HCC_RESET_BH_MASK);
+decl_hc_attribute(reset_bh);
+
+/* Power Down Backup Host Command */
+decl_hc_store_function(power_down_bh,HCF_HCC,HCC_POWER_DOWN_BH_MASK);
+decl_hc_show_function(power_down_bh,HCF_HCC,HCC_POWER_DOWN_BH_MASK);
+decl_hc_attribute(power_down_bh);
+
+/* Backup Host S1 PRST Response (1=hard reset, 0=ignore)*/
+decl_hc_store_function(bh_s1_response,HCF_HCC,HCC_BH_S1_RESPONSE_MASK);
+decl_hc_show_function(bh_s1_response,HCF_HCC,HCC_BH_S1_RESPONSE_MASK);
+decl_hc_attribute(bh_s1_response);
+
+/* Active Host S1 PRST Response (1=hard reset, 0=ignore)*/
+decl_hc_store_function(ah_s1_response,HCF_HCC,HCC_AH_S1_RESPONSE_MASK);
+decl_hc_show_function(ah_s1_response,HCF_HCC,HCC_AH_S1_RESPONSE_MASK);
+decl_hc_attribute(ah_s1_response);
+
+/**********************************************************************
+ * Isolation Configuration register (ISOC) attributes
+ */
+decl_hc_kobject(isoc);
+
+/* HCC Unlock Command */
+decl_hc_store_function(unlock,HCF_ISOC,ISOC_UNLOCK_MASK);
+decl_hc_show_function(unlock,HCF_ISOC,ISOC_UNLOCK_MASK);
+decl_hc_attribute(unlock);
+
+/* S1 Backplane Reset Mask */
+decl_hc_store_function(s1_bp_reset_mask,HCF_ISOC,ISOC_S1_BP_RESET_MASK);
+decl_hc_show_function(s1_bp_reset_mask,HCF_ISOC,ISOC_S1_BP_RESET_MASK);
+decl_hc_attribute(s1_bp_reset_mask);
+
+/* S2 Backplane Reset Mask */
+decl_hc_store_function(s2_bp_reset_mask,HCF_ISOC,ISOC_S2_BP_RESET_MASK);
+decl_hc_show_function(s2_bp_reset_mask,HCF_ISOC,ISOC_S2_BP_RESET_MASK);
+decl_hc_attribute(s2_bp_reset_mask);
+
+/* Backplane Interrupt Mask */
+decl_hc_store_function(bp_interrupt_mask,HCF_ISOC,ISOC_BP_INTERRUPT_MASK);
+decl_hc_show_function(bp_interrupt_mask,HCF_ISOC,ISOC_BP_INTERRUPT_MASK);
+decl_hc_attribute(bp_interrupt_mask);
+
+/* Hostile Configuration (what happens on a hostile takeover)*/
+decl_hc_store_function(hostile,HCF_ISOC,ISOC_HOSTILE_MASK);
+decl_hc_show_function(hostile,HCF_ISOC,ISOC_HOSTILE_MASK);
+decl_hc_attribute(hostile);
+
+/* Friendly Configuration (what happens on a friendly takeover)*/
+decl_hc_store_function(friendly,HCF_ISOC,ISOC_FRIENDLY_MASK);
+decl_hc_show_function(friendly,HCF_ISOC,ISOC_FRIENDLY_MASK);
+decl_hc_attribute(friendly);
+
+
+/**********************************************************************
+ * Fault Configuration register (FLTC) attributes
+ */
+decl_hc_kobject(fltc);
+
+/* Watchdog Timeout Configuration */
+decl_hc_store_function(wd_timeout,HCF_FLTC,FLTC_WD_TIMEOUT_MASK);
+decl_hc_show_function(wd_timeout,HCF_FLTC,FLTC_WD_TIMEOUT_MASK);
+decl_hc_attribute(wd_timeout);
+
+/* PERR Configuration */
+decl_hc_store_function(perr,HCF_FLTC,FLTC_PERR_MASK);
+decl_hc_show_function(perr,HCF_FLTC,FLTC_PERR_MASK);
+decl_hc_attribute(perr);
+
+/* IOCHK Configuration */
+decl_hc_store_function(iochk,HCF_FLTC,FLTC_IOCHK_MASK);
+decl_hc_show_function(iochk,HCF_FLTC,FLTC_IOCHK_MASK);
+decl_hc_attribute(iochk);
+
+/* NMI Configuration */
+decl_hc_store_function(nmi,HCF_FLTC,FLTC_NMI_MASK);
+decl_hc_show_function(nmi,HCF_FLTC,FLTC_NMI_MASK);
+decl_hc_attribute(nmi);
+
+/* B0_SERR Configuration */
+decl_hc_store_function(b0_serr,HCF_FLTC,FLTC_B0_SERR_MASK);
+decl_hc_show_function(b0_serr,HCF_FLTC,FLTC_B0_SERR_MASK);
+decl_hc_attribute(b0_serr);
+
+/* CPUTEMP Configuration */
+decl_hc_store_function(cputemp,HCF_FLTC,FLTC_CPUTEMP_MASK);
+decl_hc_show_function(cputemp,HCF_FLTC,FLTC_CPUTEMP_MASK);
+decl_hc_attribute(cputemp);
+
+/* Power Fail Configuration */
+decl_hc_store_function(power_fail,HCF_FLTC,FLTC_POWER_FAIL_MASK);
+decl_hc_show_function(power_fail,HCF_FLTC,FLTC_POWER_FAIL_MASK);
+decl_hc_attribute(power_fail);
+
+/* Eject BH Configuration */
+decl_hc_store_function(eject_bh,HCF_FLTC,FLTC_EJECT_BH_MASK);
+decl_hc_show_function(eject_bh,HCF_FLTC,FLTC_EJECT_BH_MASK);
+decl_hc_attribute(eject_bh);
+
+/* Eject AH Configuration */
+decl_hc_store_function(eject_ah,HCF_FLTC,FLTC_EJECT_AH_MASK);
+decl_hc_show_function(eject_ah,HCF_FLTC,FLTC_EJECT_AH_MASK);
+decl_hc_attribute(eject_ah);
+
+/* Soft Reset Configuration */
+decl_hc_store_function(soft_reset,HCF_FLTC,FLTC_SOFT_RESET_MASK);
+decl_hc_show_function(soft_reset,HCF_FLTC,FLTC_SOFT_RESET_MASK);
+decl_hc_attribute(soft_reset);
+
+/* Hard Reset Configuration */
+decl_hc_store_function(hard_reset,HCF_FLTC,FLTC_HARD_RESET_MASK);
+decl_hc_show_function(hard_reset,HCF_FLTC,FLTC_HARD_RESET_MASK);
+decl_hc_attribute(hard_reset);
+
+/**********************************************************************
+ * PCI Mezzanine Card (PMC) Control register
+ */
+decl_hc_kobject(pmcc);
+
+/* Input from PMC1 BUSMODE[1] (cleared if present and configured) */
+decl_hc_store_function(pmc1_status,HCF_PMCC,PMCC_PMC1_STATUS_MASK);
+decl_hc_show_function(pmc1_status,HCF_PMCC,PMCC_PMC1_STATUS_MASK);
+decl_hc_attribute(pmc1_status);
+
+/* Set to enable PMC1 as a PCI device */
+decl_hc_store_function(pmc1_command2,HCF_PMCC,PMCC_PMC1_COMMAND2_MASK);
+decl_hc_show_function(pmc1_command2,HCF_PMCC,PMCC_PMC1_COMMAND2_MASK);
+decl_hc_attribute(pmc1_command2);
+
+/* Clear to enable PMC1 as a PCI device */
+decl_hc_store_function(pmc1_command4,HCF_PMCC,PMCC_PMC1_COMMAND4_MASK);
+decl_hc_show_function(pmc1_command4,HCF_PMCC,PMCC_PMC1_COMMAND4_MASK);
+decl_hc_attribute(pmc1_command4);
+
+/* Input from PMC2 BUSMODE[1] (cleared if present and configured) */
+decl_hc_store_function(pmc2_status,HCF_PMCC,PMCC_PMC2_STATUS_MASK);
+decl_hc_show_function(pmc2_status,HCF_PMCC,PMCC_PMC2_STATUS_MASK);
+decl_hc_attribute(pmc2_status);
+
+/* Set to enable PMC2 as a PCI device */
+decl_hc_store_function(pmc2_command2,HCF_PMCC,PMCC_PMC2_COMMAND2_MASK);
+decl_hc_show_function(pmc2_command2,HCF_PMCC,PMCC_PMC2_COMMAND2_MASK);
+decl_hc_attribute(pmc2_command2);
+
+/* Clear to enable PMC2 as a PCI device */
+decl_hc_store_function(pmc2_command4,HCF_PMCC,PMCC_PMC2_COMMAND4_MASK);
+decl_hc_show_function(pmc2_command4,HCF_PMCC,PMCC_PMC2_COMMAND4_MASK);
+decl_hc_attribute(pmc2_command4);
+
+/**********************************************************************
+ * Watchdog Control (WDC) register attributes
+ */
+decl_hc_kobject(wdc);
+
+/* Watchdog Terminal Count (prescaler counts to timeout) */
+decl_hc_store_function(terminal_count,HCF_WDC,WDC_TERMINAL_COUNT_MASK);
+decl_hc_show_function(terminal_count,HCF_WDC,WDC_TERMINAL_COUNT_MASK);
+decl_hc_attribute(terminal_count);
+
+/* Watchdog Prescaler (clock period) */
+decl_hc_store_function(prescaler,HCF_WDC,WDC_PRESCALER_MASK);
+decl_hc_show_function(prescaler,HCF_WDC,WDC_PRESCALER_MASK);
+decl_hc_attribute(prescaler);
+
+/**********************************************************************
+ * Diagnostics (DIAG) register attributes: Setting any of these bits
+ * will cause the associated fault to be simulated.
+ */
+decl_hc_kobject(diag);
+
+/* Watchdog Timeout Diagnostic */
+decl_hc_store_function(diag_wd_timeout,HCF_DIAG,DIAG_WD_TIMEOUT_MASK);
+decl_hc_show_function(diag_wd_timeout,HCF_DIAG,DIAG_WD_TIMEOUT_MASK);
+decl_hc_attribute(diag_wd_timeout);
+
+/* PERR Diagnostic */
+decl_hc_store_function(diag_perr,HCF_DIAG,DIAG_PERR_MASK);
+decl_hc_show_function(diag_perr,HCF_DIAG,DIAG_PERR_MASK);
+decl_hc_attribute(diag_perr);
+
+/* IOCHK Diagnostic */
+decl_hc_store_function(diag_iochk,HCF_DIAG,DIAG_IOCHK_MASK);
+decl_hc_show_function(diag_iochk,HCF_DIAG,DIAG_IOCHK_MASK);
+decl_hc_attribute(diag_iochk);
+
+/* NMI Diagnostic */
+decl_hc_store_function(diag_nmi,HCF_DIAG,DIAG_NMI_MASK);
+decl_hc_show_function(diag_nmi,HCF_DIAG,DIAG_NMI_MASK);
+decl_hc_attribute(diag_nmi);
+
+/* B0 SERR Diagnostic */
+decl_hc_store_function(diag_b0_serr,HCF_DIAG,DIAG_B0_SERR_MASK);
+decl_hc_show_function(diag_b0_serr,HCF_DIAG,DIAG_B0_SERR_MASK);
+decl_hc_attribute(diag_b0_serr);
+
+/* CPUTEMP Diagnostic */
+decl_hc_store_function(diag_cputemp,HCF_DIAG,DIAG_CPUTEMP_MASK);
+decl_hc_show_function(diag_cputemp,HCF_DIAG,DIAG_CPUTEMP_MASK);
+decl_hc_attribute(diag_cputemp);
+
+/* Power Fail Diagnostic */
+decl_hc_store_function(diag_power_fail,HCF_DIAG,DIAG_POWER_FAIL_MASK);
+decl_hc_show_function(diag_power_fail,HCF_DIAG,DIAG_POWER_FAIL_MASK);
+decl_hc_attribute(diag_power_fail);
+
+void create_hc_files(void *index, void *data)
+{
+ if(subsystem_register(&rhc_subsys))
+ return;
+
+ /* hci */
+ hci_obj.index = index;
+ hci_obj.data = data;
+ kobj_set_kset_s(&hci_obj, rhc_subsys);
+ kobject_register(&hci_obj.kobj);
+ sysfs_create_file(&hci_obj.kobj, &hcf_interrupt_mask_attr.attr);
+ sysfs_create_file(&hci_obj.kobj, &fault_interrupt_mask_attr.attr);
+ sysfs_create_file(&hci_obj.kobj, &serial_interrupt_mask_attr.attr);
+
+ /* hcc */
+ hcc_obj.index = index;
+ hcc_obj.data = data;
+ kobj_set_kset_s(&hcc_obj, rhc_subsys);
+ kobject_register(&hcc_obj.kobj);
+ sysfs_create_file(&hcc_obj.kobj, &reset_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &diagnostics_mode_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &configuration_mode_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &s2_bp_reset_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &s1_bp_reset_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &warm_boot_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &initiate_takeover_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &wd_enable_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &reset_bh_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &power_down_bh_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &bh_s1_response_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &ah_s1_response_attr.attr);
+
+ /* isoc */
+ isoc_obj.index = index;
+ isoc_obj.data = data;
+ kobj_set_kset_s(&isoc_obj, rhc_subsys);
+ kobject_register(&isoc_obj.kobj);
+ sysfs_create_file(&isoc_obj.kobj, &unlock_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &s1_bp_reset_mask_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &s2_bp_reset_mask_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &bp_interrupt_mask_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &hostile_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &friendly_attr.attr);
+
+ /* fltc */
+ fltc_obj.index = index;
+ fltc_obj.data = data;
+ kobj_set_kset_s(&fltc_obj, rhc_subsys);
+ kobject_register(&fltc_obj.kobj);
+ sysfs_create_file(&fltc_obj.kobj, &wd_timeout_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &perr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &iochk_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &nmi_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &b0_serr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &cputemp_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &power_fail_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_bh_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_ah_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &soft_reset_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &hard_reset_attr.attr);
+
+ /* pmcc */
+ pmcc_obj.index = index;
+ pmcc_obj.data = data;
+ kobj_set_kset_s(&pmcc_obj, rhc_subsys);
+ kobject_register(&pmcc_obj.kobj);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc1_status_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc1_command2_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc1_command4_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc2_status_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc2_command2_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc2_command4_attr.attr);
+
+ /* wdc */
+ wdc_obj.index = index;
+ wdc_obj.data = data;
+ kobj_set_kset_s(&wdc_obj, rhc_subsys);
+ kobject_register(&wdc_obj.kobj);
+ sysfs_create_file(&wdc_obj.kobj, &terminal_count_attr.attr);
+ sysfs_create_file(&wdc_obj.kobj, &prescaler_attr.attr);
+
+ /* diag */
+ diag_obj.index = index;
+ diag_obj.data = data;
+ kobj_set_kset_s(&diag_obj, rhc_subsys);
+ kobject_register(&diag_obj.kobj);
+ sysfs_create_file(&diag_obj.kobj, &diag_wd_timeout_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_perr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_iochk_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_nmi_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_b0_serr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_cputemp_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_power_fail_attr.attr);
+}
+
+void remove_hc_files(void)
+{
+ /* hci */
+ sysfs_create_file(&hci_obj.kobj, &hcf_interrupt_mask_attr.attr);
+ sysfs_create_file(&hci_obj.kobj, &fault_interrupt_mask_attr.attr);
+ sysfs_create_file(&hci_obj.kobj, &serial_interrupt_mask_attr.attr);
+ kobject_unregister(&hci_obj.kobj);
+
+ /* hcc */
+ sysfs_create_file(&hcc_obj.kobj, &reset_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &diagnostics_mode_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &configuration_mode_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &s2_bp_reset_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &s1_bp_reset_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &warm_boot_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &initiate_takeover_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &wd_enable_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &reset_bh_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &power_down_bh_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &bh_s1_response_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &ah_s1_response_attr.attr);
+ kobject_unregister(&hcc_obj.kobj);
+
+ /* isoc */
+ sysfs_create_file(&isoc_obj.kobj, &unlock_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &s1_bp_reset_mask_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &s2_bp_reset_mask_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &bp_interrupt_mask_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &hostile_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &friendly_attr.attr);
+ kobject_unregister(&isoc_obj.kobj);
+
+ /* fltc */
+ sysfs_create_file(&fltc_obj.kobj, &wd_timeout_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &perr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &iochk_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &nmi_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &b0_serr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &cputemp_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &power_fail_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_bh_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_ah_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &soft_reset_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &hard_reset_attr.attr);
+ kobject_unregister(&fltc_obj.kobj);
+
+ /* pmcc */
+ sysfs_create_file(&pmcc_obj.kobj, &pmc1_status_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc1_command2_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc1_command4_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc2_status_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc2_command2_attr.attr);
+ sysfs_create_file(&pmcc_obj.kobj, &pmc2_command4_attr.attr);
+ kobject_unregister(&pmcc_obj.kobj);
+
+ /* wdc */
+ sysfs_create_file(&wdc_obj.kobj, &terminal_count_attr.attr);
+ sysfs_create_file(&wdc_obj.kobj, &prescaler_attr.attr);
+ kobject_unregister(&wdc_obj.kobj);
+
+ /* diag */
+ sysfs_create_file(&diag_obj.kobj, &diag_wd_timeout_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_perr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_iochk_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_nmi_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_b0_serr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_cputemp_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_power_fail_attr.attr);
+ kobject_unregister(&diag_obj.kobj);
+
+
+ subsystem_unregister(&rhc_subsys);
+}
+



Attachments:
cpci-latest-2.5.59-bk.diff (46.99 kB)

2003-02-04 23:02:45

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Tue, Feb 04, 2003 at 02:33:15PM -0800, Rusty Lynch wrote:
> Last week I finally got access to a decent (but old) technical specification
> for the ZT5550 redundant host controller. The document was published for
> the ZT5550C, but I am hoping that newer versions of the RHC just add more
> functionality to all the documented reserved bits in the document I am looking
> at.
>
> The following patch adds a sysfs interface to most of the bits accessible
> via the indirect register (through the HCINDEX and HCDATA addresses in the
> Command and Status Register (CSR). The only bits I did not add access to
> were the ones that are cleared by reading. There are a lot of bits to get
> access to, which makes this patch a little bigger then I first expected,
> so I created a new config option so only people who actually want to mess
> with the RHC would pay for it.
>
> Enabling this code will cause a new directory called zt5550_rhc to be
> created in the root of sysfs, with the following tree:

Ick, don't place directories in the root of sysfs, unless you want Pat
to come after you with a big stick.

What's wrong with putting this directory either under the pci device
that is the zt5550 (if it is a pci device), or at the least, under the
devices/ directory.

Other than that, I like your macro abuse :)

thanks,

greg k-h

2003-02-04 23:11:38

by Rusty Lynch

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Tue, 2003-02-04 at 15:08, Greg KH wrote:
> On Tue, Feb 04, 2003 at 02:33:15PM -0800, Rusty Lynch wrote:
> > Last week I finally got access to a decent (but old) technical specification
> > for the ZT5550 redundant host controller. The document was published for
> > the ZT5550C, but I am hoping that newer versions of the RHC just add more
> > functionality to all the documented reserved bits in the document I am looking
> > at.
> >
> > The following patch adds a sysfs interface to most of the bits accessible
> > via the indirect register (through the HCINDEX and HCDATA addresses in the
> > Command and Status Register (CSR). The only bits I did not add access to
> > were the ones that are cleared by reading. There are a lot of bits to get
> > access to, which makes this patch a little bigger then I first expected,
> > so I created a new config option so only people who actually want to mess
> > with the RHC would pay for it.
> >
> > Enabling this code will cause a new directory called zt5550_rhc to be
> > created in the root of sysfs, with the following tree:
>
> Ick, don't place directories in the root of sysfs, unless you want Pat
> to come after you with a big stick.
>
> What's wrong with putting this directory either under the pci device
> that is the zt5550 (if it is a pci device), or at the least, under the
> devices/ directory.

It was just laziness. I can create a new subsystem that isn't rooted in
any other subsystem without any other information. I'll go figure out
how to root this in the zt5550 device directory.

>
> Other than that, I like your macro abuse :)
>

Yea, one thing leads to another. If wouldn't have stopped myself then
the entire file would have been implemented as one macro line.

> thanks,
>
> greg k-h


2003-02-05 20:48:30

by Rusty Lynch

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

Here is a second version of the zt5550 reduncant host controller sysfs
interface patch. I have first of all removed several of the more advanced
(and therefore more dangerous) chip features, and also moved the root
of these files to the 'zt5550_hc' directory that was already being created
in bus/pci/drivers/ so that the directory view now looks like:

[root@cpci-b root]# tree /sysfs/bus/pci/drivers/zt5550_hc/rhc/
/sysfs/bus/pci/drivers/zt5550_hc/rhc/
|-- diag
| |-- diag_b0_serr
| |-- diag_cputemp
| |-- diag_iochk
| |-- diag_nmi
| |-- diag_perr
| |-- diag_power_fail
| `-- diag_wd_timeout
|-- fltc
| |-- b0_serr
| |-- cputemp
| |-- eject_ah
| |-- eject_bh
| |-- hard_reset
| |-- iochk
| |-- nmi
| |-- perr
| |-- power_fail
| |-- soft_reset
| `-- wd_timeout
|-- hcc
| |-- diagnostics_mode
| |-- power_down_bh
| `-- reset_bh
|-- isoc
| |-- friendly
| |-- hostile
| `-- unlock
`-- wdc
|-- prescaler
`-- terminal_count


# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.982 -> 1.984
# drivers/hotplug/cpcihp_zt5550.h 1.2 -> 1.4
# drivers/hotplug/Kconfig 1.5 -> 1.6
# drivers/hotplug/cpcihp_zt5550.c 1.2 -> 1.4
# drivers/hotplug/Makefile 1.12 -> 1.13
# (new) -> 1.2 drivers/hotplug/cpcihp_zt5550_rhc.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/04 [email protected] 1.983
# Adding a sysfs inteface for the zt5550 redundant host controller
# --------------------------------------------
# 03/02/05 [email protected] 1.984
# moving root of rhc sysfs files to zt5550_hc directory and remove
# some of the more advanced access files.
# --------------------------------------------
#
diff -Nru a/drivers/hotplug/Kconfig b/drivers/hotplug/Kconfig
--- a/drivers/hotplug/Kconfig Wed Feb 5 12:38:17 2003
+++ b/drivers/hotplug/Kconfig Wed Feb 5 12:38:17 2003
@@ -101,6 +101,23 @@

When in doubt, say N.

+config HOTPLUG_PCI_CPCI_ZT5550_RHC
+ bool "Ziatech ZT5550 CompactPCI RHC Sysfs Interface"
+ depends on HOTPLUG_PCI_CPCI_ZT5550
+ help
+ Say Y here if you have an Performance Technologies (formerly Intel,
+ formerly just Ziatech) Ziatech ZT5550 CompactPCI system card, and
+ would like to have configuration access to the onboard
+ Redundant Host Controller.
+
+ Saying Y here will cause a new "zt5550_rhc" directory to be created
+ in the root of your sysfs, with a directory for each of the rhc
+ indirect registers created inside the zt5550_rhc directory, and then
+ control files in each of those directorys giving user space access
+ to all of the bits in those indirect registers.
+
+ When in doubt, say N.
+
config HOTPLUG_PCI_CPCI_GENERIC
tristate "Generic port I/O CompactPCI Hotplug driver"
depends on HOTPLUG_PCI_CPCI && X86
diff -Nru a/drivers/hotplug/Makefile b/drivers/hotplug/Makefile
--- a/drivers/hotplug/Makefile Wed Feb 5 12:38:17 2003
+++ b/drivers/hotplug/Makefile Wed Feb 5 12:38:17 2003
@@ -7,6 +7,7 @@
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
+obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC) += cpcihp_zt5550_rhc.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o

pci_hotplug-objs := pci_hotplug_core.o \
diff -Nru a/drivers/hotplug/cpcihp_zt5550.c b/drivers/hotplug/cpcihp_zt5550.c
--- a/drivers/hotplug/cpcihp_zt5550.c Wed Feb 5 12:38:17 2003
+++ b/drivers/hotplug/cpcihp_zt5550.c Wed Feb 5 12:38:17 2003
@@ -35,6 +35,8 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/kobject.h>
+#include <linux/bitops.h>
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"

@@ -42,22 +44,6 @@
#define DRIVER_AUTHOR "Scott Murray <[email protected]>"
#define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver"

-#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
-#define MY_NAME "cpcihp_zt5550"
-#else
-#define MY_NAME THIS_MODULE->name
-#endif
-
-#define dbg(format, arg...) \
- do { \
- if(debug) \
- printk (KERN_DEBUG "%s: " format "\n", \
- MY_NAME , ## arg); \
- } while(0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
-
/* local variables */
static int debug;
static int poll;
@@ -75,8 +61,8 @@

/* Host controller register addresses */
static void *hc_registers;
-static void *csr_hc_index;
-static void *csr_hc_data;
+void *csr_hc_index;
+void *csr_hc_data;
static void *csr_intstat;
static void *csr_intmask;

@@ -259,12 +245,12 @@
}
dbg("registered controller");

- if(hcf_hcs & HCS_BUS1_ACTIVE) {
+ if(hcf_hcs & HCS_BUS1_ACTIVE_MASK) {
status = zt5550_register_bus(BUS1_SLOT, &bus1_dev, &bus1);
if(status)
goto init_register_error;
}
- if(hcf_hcs & HCS_BUS2_ACTIVE) {
+ if(hcf_hcs & HCS_BUS2_ACTIVE_MASK) {
status = zt5550_register_bus(BUS2_SLOT, &bus2_dev, &bus2);
if(status)
goto init_register_error;
@@ -277,6 +263,7 @@
}
dbg("started cPCI hotplug system");

+
return 0;
init_register_error:
if(bus1)
@@ -318,13 +305,20 @@

static int __init zt5550_init(void)
{
+ int rv;
+
info(DRIVER_DESC " version: " DRIVER_VERSION);
- return pci_module_init(&zt5550_hc_driver);
+ rv = pci_module_init(&zt5550_hc_driver);
+ if (!rv)
+ create_hc_files(csr_hc_index,csr_hc_data,&zt5550_hc_driver);
+
+ return rv;
}

static void __exit
zt5550_exit(void)
{
+ remove_hc_files();
pci_unregister_driver(&zt5550_hc_driver);
release_region(ENUM_PORT, 1);
}
diff -Nru a/drivers/hotplug/cpcihp_zt5550.h b/drivers/hotplug/cpcihp_zt5550.h
--- a/drivers/hotplug/cpcihp_zt5550.h Wed Feb 5 12:38:17 2003
+++ b/drivers/hotplug/cpcihp_zt5550.h Wed Feb 5 12:38:17 2003
@@ -33,6 +33,22 @@
#ifndef _CPCIHP_ZT5550_H
#define _CPCIHP_ZT5550_H

+#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
+#define MY_NAME "cpcihp_zt5550"
+#else
+#define MY_NAME THIS_MODULE->name
+#endif
+
+#define dbg(format, arg...) \
+ do { \
+ if(debug) \
+ printk (KERN_DEBUG "%s: " format "\n", \
+ MY_NAME , ## arg); \
+ } while(0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
+
/* Direct registers */
#define CSR_HCINDEX 0x00
#define CSR_HCDATA 0x04
@@ -44,12 +60,40 @@
#define CSR_TIM0 0x10
#define CSR_TIM1 0x14

+/* Masks for bits in CSR_INTSTAT (interrupt status) direct register */
+#define INTSTAT_SERIAL_FLAG 0x01
+#define INTSTAT_FAULT_FLAG 0x02
+#define INTSTAT_HCS_FLAG 0x04
+#define INTSTAT_TIM0_FLAG 0x08
+#define INTSTAT_TIM1_FLAG 0x10
+#define INTSTAT_ENUM_FLAG 0x20
+
/* Masks for interrupt bits in CSR_INTMASK direct register */
#define INTMASK_TIM0_INT_MASK 0x01
#define INTMASK_TIM1_INT_MASK 0x02
#define INTMASK_ENUM_INT_MASK 0x04
#define INTMASK_ALL_INTS_MASK 0x07

+/* Mask for bits in CSR_ENET (ethernet routing) direct register */
+#define ENET_A_REAR 0x01
+#define ENET_B_ROUTING 0x60
+
+/* Mask for bits in the CSR_T0_C (timer #0 control) direct register */
+#define T0_C_ENABLE 0x0001
+#define T0_C_TIMEOUT_MODE 0x0002
+#define T0_C_CLOCK_SOURCE 0x000c
+#define T0_C_READ_MODE 0x0030
+#define T0_C_WRITE_MODE 0x0040
+#define T0_C_OUTPUT_FLAG 0x0080
+
+/* Mask for bits in the CSR_T1_C (timer #1 control) direct register */
+#define T1_C_ENABLE 0x0001
+#define T1_C_TIMEOUT_MODE 0x0002
+#define T1_C_CLOCK_SOURCE 0x000c
+#define T1_C_READ_MODE 0x0030
+#define T1_C_WRITE_MODE 0x0040
+#define T1_C_OUTPUT_FLAG 0x0080
+
/* Indexed registers (through CSR_HCINDEX, CSR_HCDATA) */
#define HCF_HCI 0x04
#define HCF_HCS 0x08
@@ -65,32 +109,233 @@
#define HCF_SDO 0x38
#define HCF_SDI 0x3C

-/* Masks for interrupt bits in HCF_HCI indexed register */
+/* Masks for interrupt bits in HCF_HCI */
+/* (host controller interrupt) indexed register */
#define HCI_SERIAL_INT_MASK 0x01
#define HCI_FAULT_INT_MASK 0x02
#define HCI_HCF_INT_MASK 0x04
#define HCI_ALL_INTS_MASK 0x07

-/* Masks for the bits in the HCF_HCS indexed register */
-#define HCS_HA 0x00000001
-#define HCS_ACTIVE 0x00000002
-#define HCS_RH_STATE 0x00000004
-#define HCS_HARD_RESET 0x00000008
-#define HCS_SOFT_RESET 0x00000010
-#define HCS_RH_ALIVE 0x00000020
-#define HCS_SWITCH_OVER 0x00000040
-#define HCS_TAKEOVER_TYPE 0x00000080
-#define HCS_BUS1_ACTIVE 0x00000100
-#define HCS_BUS2_ACTIVE 0x00000200
-#define HCS_SPLIT_MODE_ERROR 0x00000400
+/* Masks for the bits in the HCF_HCS */
+/* (host controller status) indexed register */
+#define HCS_HA_MASK 0x00000001
+#define HCS_ACTIVE_MASK 0x00000002
+#define HCS_RH_STATE_MASK 0x00000004
+#define HCS_HARD_RESET_MASK 0x00000008
+#define HCS_SOFT_RESET_MASK 0x00000010
+#define HCS_RH_ALIVE_MASK 0x00000020
+#define HCS_SWITCH_OVER_MASK 0x00000040
+#define HCS_TAKEOVER_TYPE_MASK 0x00000080
+#define HCS_BUS1_ACTIVE_MASK 0x00000100
+#define HCS_BUS2_ACTIVE_MASK 0x00000200
+#define HCS_SPLIT_MODE_ERR_MASK 0x00000400
+
+/* Masks for the bits in the HCF_HCC */
+/* (host controller command) indexed register */
+#define HCC_RESET_MASK 0x00000001
+#define HCC_DIAG_MODE_MASK 0x00000002
+#define HCC_CONFIG_MODE_MASK 0x00000004
+#define HCC_S2_BP_RESET_MASK 0x00000008
+#define HCC_S1_BP_RESET_MASK 0x00000010
+#define HCC_WARM_BOOT_MASK 0x00000020
+#define HCC_INIT_TAKEOVER_MASK 0x00000040
+#define HCC_WD_ENABLE_MASK 0x00000080
+#define HCC_RESET_BH_MASK 0x00000100
+#define HCC_POWER_DOWN_BH_MASK 0x00000200
+#define HCC_BH_S1_RESPONSE_MASK 0x00001000
+#define HCC_AH_S1_RESPONSE_MASK 0x00002000
+
+/* Masks for the bits in the HCF_ARBC */
+/* (arbitration configuration) indexed register */
+#define ARBC_S1_GNT0_MASK 0x00000001
+#define ARBC_S1_GNT1_MASK 0x00000002
+#define ARBC_S1_GNT2_MASK 0x00000004
+#define ARBC_S1_GNT3_MASK 0x00000008
+#define ARBC_S1_GNT4_MASK 0x00000010
+#define ARBC_S1_GNT5_MASK 0x00000020
+#define ARBC_S1_GNT6_MASK 0x00000040
+#define ARBC_S1_GNT7_MASK 0x00000080
+#define ARBC_S2_GNT0_MASK 0x00000100
+#define ARBC_S2_GNT1_MASK 0x00000200
+#define ARBC_S2_GNT2_MASK 0x00000400
+#define ARBC_S2_GNT3_MASK 0x00000800
+#define ARBC_S2_GNT4_MASK 0x00001000
+#define ARBC_S2_GNT5_MASK 0x00002000
+#define ARBC_S2_GNT6_MASK 0x00004000
+#define ARBC_S2_GNT7_MASK 0x00008000
+
+/* Masks for the bits in the HCF_ISOC */
+/* (isolation configuration) indexed register */
+#define ISOC_UNLOCK_MASK 0x00000001
+#define ISOC_S1_BP_RESET_MASK 0x00000002
+#define ISOC_S2_BP_RESET_MASK 0x00000004
+#define ISOC_BP_INTERRUPT_MASK 0x00000008
+#define ISOC_HOSTILE_MASK 0x00000030
+#define ISOC_FRIENDLY_MASK 0x000000c0
+
+/* Masks for the bits in the HCF_FLTS (fault status) indexed register */
+#define FLTS_WD_TIMEOUT_MASK 0x00000001
+#define FLTS_PERR_MASK 0x00000002
+#define FLTS_IOCHK_MASK 0x00000004
+#define FLTS_NMI_MASK 0x00000008
+#define FLTS_B0_SERR_MASK 0x00000010
+#define FLTS_CPUTEMP_MASK 0x00000040
+#define FLTS_POWER_FAIL_MASK 0x00000080
+#define FLTS_EJECT_BH_MASK 0x00000100
+#define FLTS_EJECT_AH_MASK 0x00000200
+
+/* Masks for the bits in the HCF_FLTC (fault configuration) indexed register */
+#define FLTC_WD_TIMEOUT_MASK 0x00000007
+#define FLTC_PERR_MASK 0x00000038
+#define FLTC_IOCHK_MASK 0x000001c0
+#define FLTC_NMI_MASK 0x00000e00
+#define FLTC_B0_SERR_MASK 0x00007000
+#define FLTC_CPUTEMP_MASK 0x001c0000
+#define FLTC_POWER_FAIL_MASK 0x00e00000
+#define FLTC_EJECT_BH_MASK 0x07000000
+#define FLTC_EJECT_AH_MASK 0x38000000
+#define FLTC_SOFT_RESET_MASK 0x40000000
+#define FLTC_HARD_RESET_MASK 0x80000000
+
+/* Masks for the bits in the HCF_PMCC (PMC control) indexed register */
+#define PMCC_PMC1_STATUS_MASK 0x00000001
+#define PMCC_PMC1_COMMAND2_MASK 0x00000002
+#define PMCC_PMC1_COMMAND4_MASK 0x00000004
+#define PMCC_PMC2_STATUS_MASK 0x00000010
+#define PMCC_PMC2_COMMAND2_MASK 0x00000020
+#define PMCC_PMC2_COMMAND4_MASK 0x00000040
+
+/* Masks for the bits in the HCF_WDC (watchdog control) indexed register */
+#define WDC_TERMINAL_COUNT_MASK 0x0000003f
+#define WDC_PRESCALER_MASK 0x000000c0
+
+/* Masks for the bits in the HCF_DIAG (diagnostics command) indexed register */
+#define DIAG_WD_TIMEOUT_MASK 0x00000001
+#define DIAG_PERR_MASK 0x00000002
+#define DIAG_IOCHK_MASK 0x00000004
+#define DIAG_NMI_MASK 0x00000008
+#define DIAG_B0_SERR_MASK 0x00000010
+#define DIAG_CPUTEMP_MASK 0x00000040
+#define DIAG_POWER_FAIL_MASK 0x00000080
+
+/* Masks for the bits in the HCF_SERC (diagnostics command) indexed register */
+#define SERC_DATA_SENT 0x00000001
+#define SERC_DATA_RECIEVED 0x00000002
+#define SERC_SDO_FLAG_ENABLE 0x00000004
+#define SERC_SDI_FLAG_ENABLE 0x00000008
+#define SERC_HCSI_OFF 0x00000010
+#define SERC_FIND_TOKEN 0x00000020

/* CompactPCI bus segment device slot numbers */
#define BUS1_SLOT 0x08
#define BUS2_SLOT 0x0C

+/* I/O port for setting and configuring watchdog timer */
+#define WDT_PORT 0x79
+
+/* Masks for bits written/read from the watchdog timer port */
+#define WDT_TERMINAL_COUNT 0x07
+#define WDT_FIRST_STAGE_ENABLE 0x10
+#define WDT_RESET_ENABLE 0x20
+#define WDT_FIRST_STAGE_MONITOR 0x40
+#define WDT_RESET_MONITOR 0x80
+
/* Digital I/O port storing ENUM# */
#define ENUM_PORT 0xE1
/* Mask to get to the ENUM# bit on the bus */
#define ENUM_MASK 0x40

+#define hcf_read(index, value, csr_hc_index, csr_hc_data) \
+ { \
+ writeb((u8) index, csr_hc_index); \
+ value = readl(csr_hc_data); \
+ dbg("hcf_read(0x%08x, 0x%08x)",index,value); \
+ }
+
+#define hcf_write(index, value, csr_hc_index, csr_hc_data) \
+ { \
+ writeb((u8) index, csr_hc_index); \
+ writel(value, csr_hc_data); \
+ dbg("hcf_write(0x%08x, 0x%08x)",index,value); \
+ }
+
+#define hcf_set_bit(index, bit, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ hcf_write(index, tmp|bit, csr_hc_index, csr_hc_data); \
+ dbg("hcf_set_bit(0x%08x, 0x%08x)",index,bit); \
+ }
+
+#define hcf_clear_bit(index, bit, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ hcf_write(index, tmp & ~bit, csr_hc_index, csr_hc_data); \
+ dbg("hcf_clear_bit(0x%08x, 0x%08x)",index,bit); \
+ }
+
+#define hcf_write_bits(index, mask, request, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ dbg("hcf_write_bits(0x%08x, 0x%08x, 0x%08x)", \
+ index,mask,request); \
+ request = request << (generic_ffs(mask) - 1); \
+ request &= mask; \
+ request |= ~mask; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ tmp |= mask; \
+ tmp &= request; \
+ hcf_write(index, tmp, csr_hc_index, csr_hc_data); \
+ }
+
+#define hcf_read_bits(index, mask, value, csr_hc_index, csr_hc_data) \
+ { \
+ hcf_read(index, value, csr_hc_index, csr_hc_data); \
+ value = (mask&value)>>(generic_ffs(mask) - 1); \
+ dbg("hcf_read_bits(0x%08x, 0x%08x, 0x%08x)", \
+ index,mask,value); \
+ }
+
+#define decl_hc_attribute(_name) \
+static struct rhc_attribute _name##_attr = { \
+ .attr = { .name = __stringify(_name), .mode = 0644 }, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+}
+
+#define decl_hc_kobject(_name) \
+static struct rhc _name##_obj = { \
+ .kobj.name = __stringify(_name), \
+}
+
+
+#define decl_hc_show_function(_name, _index, _mask) \
+static ssize_t _name##_show(struct rhc * p, char * page) \
+{ \
+ int tmp; \
+ hcf_read_bits(_index, _mask, tmp, p->index, p->data); \
+ return sprintf(page,"%d\n", tmp); \
+}
+
+#define decl_hc_store_function(_name, _index, _mask) \
+static ssize_t _name##_store(struct rhc * p, const char * page, size_t count) \
+{ \
+ int request; \
+ if (sscanf(page, "%i", &request)) {\
+ hcf_write_bits(_index, _mask, request, p->index, p->data); \
+ return count; \
+ } \
+ return -EINVAL; \
+}
+
+#ifdef CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC
+extern void create_hc_files(void *,void *,struct pci_driver *);
+extern void remove_hc_files(void);
+#else /* !CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC */
+static inline void create_hc_files(void *i,void *d,struct pci_driver *p){}
+static inline void remove_hc_files(void){}
+#endif
+
#endif /* _CPCIHP_ZT5550_H */
+
diff -Nru a/drivers/hotplug/cpcihp_zt5550_rhc.c b/drivers/hotplug/cpcihp_zt5550_rhc.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/hotplug/cpcihp_zt5550_rhc.c Wed Feb 5 12:38:17 2003
@@ -0,0 +1,365 @@
+/*
+ * cpcihp_zt5550.c
+ *
+ * Intel/Ziatech ZT5550 CompactPCI Redundant Host Controller Sysfs Interface
+ *
+ * Copyright 2002 SOMA Networks, Inc.
+ * Copyright 2001 Intel San Luis Obispo
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/kobject.h>
+#include <linux/bitops.h>
+#include "cpci_hotplug.h"
+#include "cpcihp_zt5550.h"
+
+extern int debug;
+extern void *csr_hc_index;
+extern void *csr_hc_data;
+
+struct rhc {
+ void *index;
+ void *data;
+ struct kobject kobj;
+};
+struct rhc_attribute {
+ struct attribute attr;
+ ssize_t (*show) (struct rhc *,char *);
+ ssize_t (*store)(struct rhc *,const char *, size_t);
+};
+
+static ssize_t rhc_attr_show(struct kobject * kobj,
+ struct attribute * attr,
+ char * page)
+{
+ struct rhc * i = container_of(kobj,struct rhc,kobj);
+ struct rhc_attribute * rhc_attr =
+ container_of(attr,struct rhc_attribute,attr);
+
+ return rhc_attr->show ? rhc_attr->show(i,page) : 0;
+}
+
+static ssize_t rhc_attr_store(struct kobject * kobj,
+ struct attribute * attr,
+ const char * page,
+ size_t count)
+{
+ struct rhc * i = container_of(kobj,struct rhc,kobj);
+ struct rhc_attribute * rhc_attr =
+ container_of(attr,struct rhc_attribute,attr);
+
+ return rhc_attr->store ? rhc_attr->store(i,page,count) : 0;
+}
+
+static struct sysfs_ops rhc_sysfs_ops = {
+ .show = rhc_attr_show,
+ .store = rhc_attr_store,
+};
+
+static struct kobj_type rhc_ktype = {
+ .sysfs_ops = &rhc_sysfs_ops
+};
+
+static struct subsystem rhc_subsys = {
+ .kset = {
+ .kobj = { .name = "rhc" },
+ .ktype = &rhc_ktype,
+ }
+};
+
+/**********************************************************************
+ * Host Control Command attributes
+ * NOTE: The HCC register is by default locked. To change any
+ * value, first unlock by writing a '1' to the UNLOCK bit
+ * in the ISOC register.
+ */
+decl_hc_kobject(hcc);
+
+/* Diagnostics Mode Command */
+decl_hc_store_function(diagnostics_mode,HCF_HCC,HCC_DIAG_MODE_MASK);
+decl_hc_show_function(diagnostics_mode,HCF_HCC,HCC_DIAG_MODE_MASK);
+decl_hc_attribute(diagnostics_mode);
+
+/* Reset Backup Host Command*/
+decl_hc_store_function(reset_bh,HCF_HCC,HCC_RESET_BH_MASK);
+decl_hc_show_function(reset_bh,HCF_HCC,HCC_RESET_BH_MASK);
+decl_hc_attribute(reset_bh);
+
+/* Power Down Backup Host Command */
+decl_hc_store_function(power_down_bh,HCF_HCC,HCC_POWER_DOWN_BH_MASK);
+decl_hc_show_function(power_down_bh,HCF_HCC,HCC_POWER_DOWN_BH_MASK);
+decl_hc_attribute(power_down_bh);
+
+/**********************************************************************
+ * Isolation Configuration register (ISOC) attributes
+ */
+decl_hc_kobject(isoc);
+
+/* Hostile Configuration (what happens on a hostile takeover)*/
+decl_hc_store_function(hostile,HCF_ISOC,ISOC_HOSTILE_MASK);
+decl_hc_show_function(hostile,HCF_ISOC,ISOC_HOSTILE_MASK);
+decl_hc_attribute(hostile);
+
+/* Friendly Configuration (what happens on a friendly takeover)*/
+decl_hc_store_function(friendly,HCF_ISOC,ISOC_FRIENDLY_MASK);
+decl_hc_show_function(friendly,HCF_ISOC,ISOC_FRIENDLY_MASK);
+decl_hc_attribute(friendly);
+
+/* HCC Unlock Command */
+decl_hc_store_function(unlock,HCF_ISOC,ISOC_UNLOCK_MASK);
+decl_hc_show_function(unlock,HCF_ISOC,ISOC_UNLOCK_MASK);
+decl_hc_attribute(unlock);
+
+/**********************************************************************
+ * Fault Configuration register (FLTC) attributes
+ */
+decl_hc_kobject(fltc);
+
+/* Watchdog Timeout Configuration */
+decl_hc_store_function(wd_timeout,HCF_FLTC,FLTC_WD_TIMEOUT_MASK);
+decl_hc_show_function(wd_timeout,HCF_FLTC,FLTC_WD_TIMEOUT_MASK);
+decl_hc_attribute(wd_timeout);
+
+/* PERR Configuration */
+decl_hc_store_function(perr,HCF_FLTC,FLTC_PERR_MASK);
+decl_hc_show_function(perr,HCF_FLTC,FLTC_PERR_MASK);
+decl_hc_attribute(perr);
+
+/* IOCHK Configuration */
+decl_hc_store_function(iochk,HCF_FLTC,FLTC_IOCHK_MASK);
+decl_hc_show_function(iochk,HCF_FLTC,FLTC_IOCHK_MASK);
+decl_hc_attribute(iochk);
+
+/* NMI Configuration */
+decl_hc_store_function(nmi,HCF_FLTC,FLTC_NMI_MASK);
+decl_hc_show_function(nmi,HCF_FLTC,FLTC_NMI_MASK);
+decl_hc_attribute(nmi);
+
+/* B0_SERR Configuration */
+decl_hc_store_function(b0_serr,HCF_FLTC,FLTC_B0_SERR_MASK);
+decl_hc_show_function(b0_serr,HCF_FLTC,FLTC_B0_SERR_MASK);
+decl_hc_attribute(b0_serr);
+
+/* CPUTEMP Configuration */
+decl_hc_store_function(cputemp,HCF_FLTC,FLTC_CPUTEMP_MASK);
+decl_hc_show_function(cputemp,HCF_FLTC,FLTC_CPUTEMP_MASK);
+decl_hc_attribute(cputemp);
+
+/* Power Fail Configuration */
+decl_hc_store_function(power_fail,HCF_FLTC,FLTC_POWER_FAIL_MASK);
+decl_hc_show_function(power_fail,HCF_FLTC,FLTC_POWER_FAIL_MASK);
+decl_hc_attribute(power_fail);
+
+/* Eject BH Configuration */
+decl_hc_store_function(eject_bh,HCF_FLTC,FLTC_EJECT_BH_MASK);
+decl_hc_show_function(eject_bh,HCF_FLTC,FLTC_EJECT_BH_MASK);
+decl_hc_attribute(eject_bh);
+
+/* Eject AH Configuration */
+decl_hc_store_function(eject_ah,HCF_FLTC,FLTC_EJECT_AH_MASK);
+decl_hc_show_function(eject_ah,HCF_FLTC,FLTC_EJECT_AH_MASK);
+decl_hc_attribute(eject_ah);
+
+/* Soft Reset Configuration */
+decl_hc_store_function(soft_reset,HCF_FLTC,FLTC_SOFT_RESET_MASK);
+decl_hc_show_function(soft_reset,HCF_FLTC,FLTC_SOFT_RESET_MASK);
+decl_hc_attribute(soft_reset);
+
+/* Hard Reset Configuration */
+decl_hc_store_function(hard_reset,HCF_FLTC,FLTC_HARD_RESET_MASK);
+decl_hc_show_function(hard_reset,HCF_FLTC,FLTC_HARD_RESET_MASK);
+decl_hc_attribute(hard_reset);
+
+/**********************************************************************
+ * Diagnostics (DIAG) register attributes: Setting any of these bits
+ * will cause the associated fault to be simulated.
+ */
+decl_hc_kobject(diag);
+
+/* Watchdog Timeout Diagnostic */
+decl_hc_store_function(diag_wd_timeout,HCF_DIAG,DIAG_WD_TIMEOUT_MASK);
+decl_hc_show_function(diag_wd_timeout,HCF_DIAG,DIAG_WD_TIMEOUT_MASK);
+decl_hc_attribute(diag_wd_timeout);
+
+/* PERR Diagnostic */
+decl_hc_store_function(diag_perr,HCF_DIAG,DIAG_PERR_MASK);
+decl_hc_show_function(diag_perr,HCF_DIAG,DIAG_PERR_MASK);
+decl_hc_attribute(diag_perr);
+
+/* IOCHK Diagnostic */
+decl_hc_store_function(diag_iochk,HCF_DIAG,DIAG_IOCHK_MASK);
+decl_hc_show_function(diag_iochk,HCF_DIAG,DIAG_IOCHK_MASK);
+decl_hc_attribute(diag_iochk);
+
+/* NMI Diagnostic */
+decl_hc_store_function(diag_nmi,HCF_DIAG,DIAG_NMI_MASK);
+decl_hc_show_function(diag_nmi,HCF_DIAG,DIAG_NMI_MASK);
+decl_hc_attribute(diag_nmi);
+
+/* B0 SERR Diagnostic */
+decl_hc_store_function(diag_b0_serr,HCF_DIAG,DIAG_B0_SERR_MASK);
+decl_hc_show_function(diag_b0_serr,HCF_DIAG,DIAG_B0_SERR_MASK);
+decl_hc_attribute(diag_b0_serr);
+
+/* CPUTEMP Diagnostic */
+decl_hc_store_function(diag_cputemp,HCF_DIAG,DIAG_CPUTEMP_MASK);
+decl_hc_show_function(diag_cputemp,HCF_DIAG,DIAG_CPUTEMP_MASK);
+decl_hc_attribute(diag_cputemp);
+
+/* Power Fail Diagnostic */
+decl_hc_store_function(diag_power_fail,HCF_DIAG,DIAG_POWER_FAIL_MASK);
+decl_hc_show_function(diag_power_fail,HCF_DIAG,DIAG_POWER_FAIL_MASK);
+decl_hc_attribute(diag_power_fail);
+
+/**********************************************************************
+ * Watchdog Control (WDC) register attributes
+ */
+decl_hc_kobject(wdc);
+
+/* Watchdog Terminal Count (prescaler counts to timeout) */
+decl_hc_store_function(terminal_count,HCF_WDC,WDC_TERMINAL_COUNT_MASK);
+decl_hc_show_function(terminal_count,HCF_WDC,WDC_TERMINAL_COUNT_MASK);
+decl_hc_attribute(terminal_count);
+
+/* Watchdog Prescaler (clock period) */
+decl_hc_store_function(prescaler,HCF_WDC,WDC_PRESCALER_MASK);
+decl_hc_show_function(prescaler,HCF_WDC,WDC_PRESCALER_MASK);
+decl_hc_attribute(prescaler);
+
+void create_hc_files(void *index, void *data, struct pci_driver *d)
+{
+ if (!index || !data || !d)
+ return;
+
+ rhc_subsys.kset.kobj.parent = &(d->driver.kobj);
+ if(subsystem_register(&rhc_subsys))
+ return;
+
+ /* hcc */
+ hcc_obj.index = index;
+ hcc_obj.data = data;
+ kobj_set_kset_s(&hcc_obj, rhc_subsys);
+ kobject_register(&hcc_obj.kobj);
+ sysfs_create_file(&hcc_obj.kobj, &diagnostics_mode_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &reset_bh_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &power_down_bh_attr.attr);
+
+ /* isoc */
+ isoc_obj.index = index;
+ isoc_obj.data = data;
+ kobj_set_kset_s(&isoc_obj, rhc_subsys);
+ kobject_register(&isoc_obj.kobj);
+ sysfs_create_file(&isoc_obj.kobj, &unlock_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &hostile_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &friendly_attr.attr);
+
+ /* fltc */
+ fltc_obj.index = index;
+ fltc_obj.data = data;
+ kobj_set_kset_s(&fltc_obj, rhc_subsys);
+ kobject_register(&fltc_obj.kobj);
+ sysfs_create_file(&fltc_obj.kobj, &wd_timeout_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &perr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &iochk_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &nmi_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &b0_serr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &cputemp_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &power_fail_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_bh_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_ah_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &soft_reset_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &hard_reset_attr.attr);
+
+ /* wdc */
+ wdc_obj.index = index;
+ wdc_obj.data = data;
+ kobj_set_kset_s(&wdc_obj, rhc_subsys);
+ kobject_register(&wdc_obj.kobj);
+ sysfs_create_file(&wdc_obj.kobj, &terminal_count_attr.attr);
+ sysfs_create_file(&wdc_obj.kobj, &prescaler_attr.attr);
+
+ /* diag */
+ diag_obj.index = index;
+ diag_obj.data = data;
+ kobj_set_kset_s(&diag_obj, rhc_subsys);
+ kobject_register(&diag_obj.kobj);
+ sysfs_create_file(&diag_obj.kobj, &diag_wd_timeout_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_perr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_iochk_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_nmi_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_b0_serr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_cputemp_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_power_fail_attr.attr);
+}
+
+void remove_hc_files(void)
+{
+ /* hcc */
+ sysfs_remove_file(&hcc_obj.kobj, &diagnostics_mode_attr.attr);
+ sysfs_remove_file(&hcc_obj.kobj, &reset_bh_attr.attr);
+ sysfs_remove_file(&hcc_obj.kobj, &power_down_bh_attr.attr);
+ kobject_unregister(&hcc_obj.kobj);
+
+ /* isoc */
+ sysfs_remove_file(&isoc_obj.kobj, &unlock_attr.attr);
+ sysfs_remove_file(&isoc_obj.kobj, &hostile_attr.attr);
+ sysfs_remove_file(&isoc_obj.kobj, &friendly_attr.attr);
+ kobject_unregister(&isoc_obj.kobj);
+
+ /* fltc */
+ sysfs_remove_file(&fltc_obj.kobj, &wd_timeout_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &perr_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &iochk_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &nmi_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &b0_serr_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &cputemp_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &power_fail_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &eject_bh_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &eject_ah_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &soft_reset_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &hard_reset_attr.attr);
+ kobject_unregister(&fltc_obj.kobj);
+
+ /* wdc */
+ sysfs_remove_file(&wdc_obj.kobj, &terminal_count_attr.attr);
+ sysfs_remove_file(&wdc_obj.kobj, &prescaler_attr.attr);
+ kobject_unregister(&wdc_obj.kobj);
+
+ /* diag */
+ sysfs_remove_file(&diag_obj.kobj, &diag_wd_timeout_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_perr_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_iochk_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_nmi_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_b0_serr_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_cputemp_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_power_fail_attr.attr);
+ kobject_unregister(&diag_obj.kobj);
+
+ subsystem_unregister(&rhc_subsys);
+}
+


2003-02-05 21:04:41

by Scott Murray

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On 5 Feb 2003, Rusty Lynch wrote:

> Here is a second version of the zt5550 reduncant host controller sysfs
> interface patch. I have first of all removed several of the more advanced
> (and therefore more dangerous) chip features, and also moved the root
> of these files to the 'zt5550_hc' directory that was already being created
> in bus/pci/drivers/ so that the directory view now looks like:

I'll likely poke around a bit more, but I can probably live with something
along these lines. My objection to exposing stuff like the HCC, ISOC, and
ARBC registers is that my gut feel is that it would be a pain to handle
them getting changed arbitrarily from userspace inside the driver,
especially if someone does the work to make it RSS capable.

Scott

PS: Are you still interested in changes to handle the ZT5550C versus
ZT5550D issues, or are things working to your satisfaction at the
moment?


--
Scott Murray
SOMA Networks, Inc.
Toronto, Ontario
e-mail: [email protected]


2003-02-05 21:41:57

by Rusty Lynch

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Wed, 2003-02-05 at 13:14, Scott Murray wrote:
> On 5 Feb 2003, Rusty Lynch wrote:
>
> > Here is a second version of the zt5550 reduncant host controller sysfs
> > interface patch. I have first of all removed several of the more advanced
> > (and therefore more dangerous) chip features, and also moved the root
> > of these files to the 'zt5550_hc' directory that was already being created
> > in bus/pci/drivers/ so that the directory view now looks like:
>
> I'll likely poke around a bit more, but I can probably live with something
> along these lines. My objection to exposing stuff like the HCC, ISOC, and
> ARBC registers is that my gut feel is that it would be a pain to handle
> them getting changed arbitrarily from userspace inside the driver,
> especially if someone does the work to make it RSS capable.
>
> Scott
>
> PS: Are you still interested in changes to handle the ZT5550C versus
> ZT5550D issues, or are things working to your satisfaction at the
> moment?
>

Since Stanley is seeing his ZT5550C work correctly with your latest
patches, I am assuming that I probably have some early engineering
version of the ZT5550C, and it isn't worth worrying about.

--rustyl

>
> --
> Scott Murray
> SOMA Networks, Inc.
> Toronto, Ontario
> e-mail: [email protected]
>


2003-02-05 22:04:42

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Wed, Feb 05, 2003 at 04:14:10PM -0500, Scott Murray wrote:
> On 5 Feb 2003, Rusty Lynch wrote:
>
> > Here is a second version of the zt5550 reduncant host controller sysfs
> > interface patch. I have first of all removed several of the more advanced
> > (and therefore more dangerous) chip features, and also moved the root
> > of these files to the 'zt5550_hc' directory that was already being created
> > in bus/pci/drivers/ so that the directory view now looks like:
>
> I'll likely poke around a bit more, but I can probably live with something
> along these lines.

Does that mean you want me to add this patch to the kernel tree?

thanks,

greg k-h

2003-02-05 22:10:45

by Scott Murray

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Wed, 5 Feb 2003, Greg KH wrote:

> On Wed, Feb 05, 2003 at 04:14:10PM -0500, Scott Murray wrote:
> > On 5 Feb 2003, Rusty Lynch wrote:
> >
> > > Here is a second version of the zt5550 reduncant host controller sysfs
> > > interface patch. I have first of all removed several of the more advanced
> > > (and therefore more dangerous) chip features, and also moved the root
> > > of these files to the 'zt5550_hc' directory that was already being created
> > > in bus/pci/drivers/ so that the directory view now looks like:
> >
> > I'll likely poke around a bit more, but I can probably live with something
> > along these lines.
>
> Does that mean you want me to add this patch to the kernel tree?

If you're happy with the sysfs changes, feel free to apply. I've got some
other fixes in hand, but I can remerge the ZT5550 driver ones later.

Scott


--
Scott Murray
SOMA Networks, Inc.
Toronto, Ontario
e-mail: [email protected]

2003-02-06 04:09:52

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Wed, Feb 05, 2003 at 12:48:48PM -0800, Rusty Lynch wrote:
> Here is a second version of the zt5550 reduncant host controller sysfs
> interface patch.

I couldnt get this to apply, sorry. Can you rediff it against the
patches I just sent to Linus?

thanks,

greg k-h

2003-02-06 18:15:52

by Rusty Lynch

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Wed, 2003-02-05 at 20:12, Greg KH wrote:
> On Wed, Feb 05, 2003 at 12:48:48PM -0800, Rusty Lynch wrote:
> > Here is a second version of the zt5550 reduncant host controller sysfs
> > interface patch.
>
> I couldnt get this to apply, sorry. Can you rediff it against the
> patches I just sent to Linus?
>
> thanks,
>
> greg k-h

It wouldn't apply because it was made on top of Scott's uniprocessor
deadlock fix. Here is a Scott's previous patch merged with today's bk
tree.

--rustyl

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.974 -> 1.975
# drivers/hotplug/cpcihp_zt5550.h 1.1 -> 1.2
# drivers/hotplug/cpci_hotplug.h 1.1 -> 1.2
# drivers/hotplug/cpci_hotplug_core.c 1.3 -> 1.4
# drivers/hotplug/cpcihp_zt5550.c 1.1 -> 1.2
# drivers/hotplug/cpci_hotplug_pci.c 1.4 -> 1.5
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/06 [email protected] 1.975
# Adding cpci uniprocessor deadlock fix
# --------------------------------------------
#
diff -Nru a/drivers/hotplug/cpci_hotplug.h b/drivers/hotplug/cpci_hotplug.h
--- a/drivers/hotplug/cpci_hotplug.h Thu Feb 6 10:18:12 2003
+++ b/drivers/hotplug/cpci_hotplug.h Thu Feb 6 10:18:12 2003
@@ -75,7 +75,6 @@
extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
extern int cpci_hp_unregister_bus(struct pci_bus *bus);
-extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn);
extern int cpci_hp_start(void);
extern int cpci_hp_stop(void);

diff -Nru a/drivers/hotplug/cpci_hotplug_core.c b/drivers/hotplug/cpci_hotplug_core.c
--- a/drivers/hotplug/cpci_hotplug_core.c Thu Feb 6 10:18:12 2003
+++ b/drivers/hotplug/cpci_hotplug_core.c Thu Feb 6 10:18:12 2003
@@ -417,34 +417,6 @@
return 0;
}

-struct slot *
-cpci_find_slot(struct pci_bus *bus, unsigned int devfn)
-{
- struct slot *slot;
- struct slot *found;
- struct list_head *tmp;
-
- if(!bus) {
- return NULL;
- }
-
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
- return NULL;
- }
- found = NULL;
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- if(slot->bus == bus && slot->devfn == devfn) {
- found = slot;
- break;
- }
- }
- spin_unlock(&list_lock);
- return found;
-}
-
/* This is the interrupt mode interrupt handler */
void
cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
@@ -915,6 +887,5 @@
EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
EXPORT_SYMBOL_GPL(cpci_hp_register_bus);
EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);
-EXPORT_SYMBOL_GPL(cpci_find_slot);
EXPORT_SYMBOL_GPL(cpci_hp_start);
EXPORT_SYMBOL_GPL(cpci_hp_stop);
diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c
--- a/drivers/hotplug/cpci_hotplug_pci.c Thu Feb 6 10:18:12 2003
+++ b/drivers/hotplug/cpci_hotplug_pci.c Thu Feb 6 10:18:12 2003
@@ -448,7 +448,7 @@
}

static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_bus)
+ struct pci_bus_wrapped *wrapped_bus)
{
int rc;
struct pci_dev *dev = wrapped_dev->dev;
@@ -461,8 +461,8 @@
* We need to fix up the hotplug representation with the Linux
* representation.
*/
- slot = cpci_find_slot(dev->bus, dev->devfn);
- if(slot) {
+ if(wrapped_dev->data) {
+ slot = (struct slot*) wrapped_dev->data;
slot->dev = dev;
}

@@ -484,7 +484,7 @@
}

static int unconfigure_visit_pci_dev_phase1(struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_bus)
+ struct pci_bus_wrapped *wrapped_bus)
{
struct pci_dev *dev = wrapped_dev->dev;

@@ -527,8 +527,8 @@
/*
* Now remove the hotplug representation.
*/
- slot = cpci_find_slot(dev->bus, dev->devfn);
- if(slot) {
+ if(wrapped_dev->data) {
+ slot = (struct slot*) wrapped_dev->data;
slot->dev = NULL;
} else {
dbg("No hotplug representation for %02x:%02x.%x",
@@ -636,6 +636,10 @@
continue;
wrapped_dev.dev = dev;
wrapped_bus.bus = slot->dev->bus;
+ if(i)
+ wrapped_dev.data = NULL;
+ else
+ wrapped_dev.data = (void*) slot;
rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
}
}
@@ -668,16 +672,21 @@
if(dev) {
wrapped_dev.dev = dev;
wrapped_bus.bus = dev->bus;
+ if(i)
+ wrapped_dev.data = NULL;
+ else
+ wrapped_dev.data = (void*) slot;
dbg("%s - unconfigure phase 1", __FUNCTION__);
rc = pci_visit_dev(&unconfigure_functions_phase1,
- &wrapped_dev, &wrapped_bus);
- if(rc) {
+ &wrapped_dev,
+ &wrapped_bus);
+ if(rc)
break;
- }

dbg("%s - unconfigure phase 2", __FUNCTION__);
rc = pci_visit_dev(&unconfigure_functions_phase2,
- &wrapped_dev, &wrapped_bus);
+ &wrapped_dev,
+ &wrapped_bus);
if(rc)
break;
}
diff -Nru a/drivers/hotplug/cpcihp_zt5550.c b/drivers/hotplug/cpcihp_zt5550.c
--- a/drivers/hotplug/cpcihp_zt5550.c Thu Feb 6 10:18:12 2003
+++ b/drivers/hotplug/cpcihp_zt5550.c Thu Feb 6 10:18:12 2003
@@ -38,7 +38,7 @@
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"

-#define DRIVER_VERSION "0.2"
+#define DRIVER_VERSION "0.3"
#define DRIVER_AUTHOR "Scott Murray <[email protected]>"
#define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver"

@@ -64,9 +64,11 @@
static struct cpci_hp_controller_ops zt5550_hpc_ops;
static struct cpci_hp_controller zt5550_hpc;

-/* Primary cPCI bus bridge device */
-static struct pci_dev *bus0_dev;
-static struct pci_bus *bus0;
+/* cPCI bus bridge devices */
+static struct pci_dev *bus1_dev;
+static struct pci_bus *bus1;
+static struct pci_dev *bus2_dev;
+static struct pci_bus *bus2;

/* Host controller device */
static struct pci_dev *hc_dev;
@@ -75,9 +77,11 @@
static void *hc_registers;
static void *csr_hc_index;
static void *csr_hc_data;
-static void *csr_int_status;
-static void *csr_int_mask;
+static void *csr_intstat;
+static void *csr_intmask;

+/* Host controller status register */
+static u32 hcf_hcs;

static int zt5550_hc_config(struct pci_dev *pdev)
{
@@ -109,23 +113,28 @@

csr_hc_index = hc_registers + CSR_HCINDEX;
csr_hc_data = hc_registers + CSR_HCDATA;
- csr_int_status = hc_registers + CSR_INTSTAT;
- csr_int_mask = hc_registers + CSR_INTMASK;
+ csr_intstat = hc_registers + CSR_INTSTAT;
+ csr_intmask = hc_registers + CSR_INTMASK;
+
+ /* Read Host Control Status register */
+ writeb((u8) HCF_HCS, csr_hc_index);
+ hcf_hcs = readl(csr_hc_data);
+ info("HCF_HCS = 0x%08x", hcf_hcs);

/*
* Disable host control, fault and serial interrupts
*/
dbg("disabling host control, fault and serial interrupts");
- writeb((u8) HC_INT_MASK_REG, csr_hc_index);
- writeb((u8) ALL_INDEXED_INTS_MASK, csr_hc_data);
+ writeb((u8) HCF_HCI, csr_hc_index);
+ writeb((u8) HCI_ALL_INTS_MASK, csr_hc_data);
dbg("disabled host control, fault and serial interrupts");

/*
- * Disable timer0, timer1 and ENUM interrupts
+ * Disable timer0, timer1 and ENUM# interrupts
*/
- dbg("disabling timer0, timer1 and ENUM interrupts");
- writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
- dbg("disabled timer0, timer1 and ENUM interrupts");
+ dbg("disabling timer0, timer1 and ENUM# interrupts");
+ writeb((u8) INTMASK_ALL_INTS_MASK, csr_intmask);
+ dbg("disabled timer0, timer1 and ENUM# interrupts");
return 0;
}

@@ -153,7 +162,7 @@

ret = 0;
if(dev_id == zt5550_hpc.dev_id) {
- reg = readb(csr_int_status);
+ reg = readb(csr_intstat);
if(reg)
ret = 1;
}
@@ -167,9 +176,9 @@
if(hc_dev == NULL) {
return -ENODEV;
}
- reg = readb(csr_int_mask);
- reg = reg & ~ENUM_INT_MASK;
- writeb(reg, csr_int_mask);
+ reg = readb(csr_intmask);
+ reg = reg & ~INTMASK_ENUM_INT_MASK;
+ writeb(reg, csr_intmask);
return 0;
}

@@ -181,16 +190,42 @@
return -ENODEV;
}

- reg = readb(csr_int_mask);
- reg = reg | ENUM_INT_MASK;
- writeb(reg, csr_int_mask);
+ reg = readb(csr_intmask);
+ reg = reg | INTMASK_ENUM_INT_MASK;
+ writeb(reg, csr_intmask);
return 0;
}

+static int __devinit zt5550_register_bus(unsigned int slot,
+ struct pci_dev **dev,
+ struct pci_bus **bus)
+{
+ int status;
+
+ /* Look for slot's device */
+ if(!(*dev = pci_find_slot(0, PCI_DEVFN(slot, 0)))) {
+ return -ENODEV;
+ }
+ if(!((*dev)->vendor == PCI_VENDOR_ID_DEC && \
+ (*dev)->device == PCI_DEVICE_ID_DEC_21154)) {
+ return -ENODEV;
+ }
+ *bus = (*dev)->subordinate;
+
+ status = cpci_hp_register_bus(*bus, 0x0a, 0x0f);
+ if(status) {
+ err("could not register cPCI hotplug bus %d", (*bus)->number);
+ } else {
+ dbg("registered bus %d", (*bus)->number);
+ }
+ return status;
+}
+
static int __devinit zt5550_hc_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int status;
+ struct resource* r;

status = zt5550_hc_config(pdev);
if(status != 0) {
@@ -198,6 +233,10 @@
}
dbg("returned from zt5550_hc_config");

+ r = request_region(ENUM_PORT, 1, "ENUM# hotswap signal register");
+ if(!r)
+ return -EBUSY;
+
memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller));
zt5550_hpc_ops.query_enum = zt5550_hc_query_enum;
zt5550_hpc.ops = &zt5550_hpc_ops;
@@ -220,31 +259,30 @@
}
dbg("registered controller");

- /* Look for first device matching cPCI bus's bridge vendor and device IDs */
- if(!(bus0_dev = pci_find_device(PCI_VENDOR_ID_DEC,
- PCI_DEVICE_ID_DEC_21154, NULL))) {
- status = -ENODEV;
- goto init_register_error;
- }
- bus0 = bus0_dev->subordinate;
-
- status = cpci_hp_register_bus(bus0, 0x0a, 0x0f);
- if(status != 0) {
- err("could not register cPCI hotplug bus");
- goto init_register_error;
+ if(hcf_hcs & HCS_BUS1_ACTIVE) {
+ status = zt5550_register_bus(BUS1_SLOT, &bus1_dev, &bus1);
+ if(status)
+ goto init_register_error;
+ }
+ if(hcf_hcs & HCS_BUS2_ACTIVE) {
+ status = zt5550_register_bus(BUS2_SLOT, &bus2_dev, &bus2);
+ if(status)
+ goto init_register_error;
}
- dbg("registered bus");

status = cpci_hp_start();
if(status != 0) {
err("could not started cPCI hotplug system");
- cpci_hp_unregister_bus(bus0);
goto init_register_error;
}
- dbg("started cpci hp system");
+ dbg("started cPCI hotplug system");

return 0;
init_register_error:
+ if(bus1)
+ cpci_hp_unregister_bus(bus1);
+ if(bus2)
+ cpci_hp_unregister_bus(bus2);
cpci_hp_unregister_controller(&zt5550_hpc);
init_hc_error:
err("status = %d", status);
@@ -256,7 +294,10 @@
static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev)
{
cpci_hp_stop();
- cpci_hp_unregister_bus(bus0);
+ if(bus1)
+ cpci_hp_unregister_bus(bus1);
+ if(bus2)
+ cpci_hp_unregister_bus(bus2);
cpci_hp_unregister_controller(&zt5550_hpc);
zt5550_hc_cleanup();
}
@@ -277,13 +318,7 @@

static int __init zt5550_init(void)
{
- struct resource* r;
-
info(DRIVER_DESC " version: " DRIVER_VERSION);
- r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
- if(!r)
- return -EBUSY;
-
return pci_module_init(&zt5550_hc_driver);
}

@@ -303,4 +338,4 @@
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
MODULE_PARM(poll, "i");
-MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not");
+MODULE_PARM_DESC(poll, "ENUM# polling mode enabled or not");
diff -Nru a/drivers/hotplug/cpcihp_zt5550.h b/drivers/hotplug/cpcihp_zt5550.h
--- a/drivers/hotplug/cpcihp_zt5550.h Thu Feb 6 10:18:12 2003
+++ b/drivers/hotplug/cpcihp_zt5550.h Thu Feb 6 10:18:12 2003
@@ -38,38 +38,55 @@
#define CSR_HCDATA 0x04
#define CSR_INTSTAT 0x08
#define CSR_INTMASK 0x09
-#define CSR_CNT0CMD 0x0C
-#define CSR_CNT1CMD 0x0E
-#define CSR_CNT0 0x10
-#define CSR_CNT1 0x14
+#define CSR_ENET 0x0A
+#define CSR_T0_C 0x0C
+#define CSR_T1_C 0x0E
+#define CSR_TIM0 0x10
+#define CSR_TIM1 0x14

/* Masks for interrupt bits in CSR_INTMASK direct register */
-#define CNT0_INT_MASK 0x01
-#define CNT1_INT_MASK 0x02
-#define ENUM_INT_MASK 0x04
-#define ALL_DIRECT_INTS_MASK 0x07
+#define INTMASK_TIM0_INT_MASK 0x01
+#define INTMASK_TIM1_INT_MASK 0x02
+#define INTMASK_ENUM_INT_MASK 0x04
+#define INTMASK_ALL_INTS_MASK 0x07

-/* Indexed registers (through CSR_INDEX, CSR_DATA) */
-#define HC_INT_MASK_REG 0x04
-#define HC_STATUS_REG 0x08
-#define HC_CMD_REG 0x0C
-#define ARB_CONFIG_GNT_REG 0x10
-#define ARB_CONFIG_CFG_REG 0x12
-#define ARB_CONFIG_REG 0x10
-#define ISOL_CONFIG_REG 0x18
-#define FAULT_STATUS_REG 0x20
-#define FAULT_CONFIG_REG 0x24
-#define WD_CONFIG_REG 0x2C
-#define HC_DIAG_REG 0x30
-#define SERIAL_COMM_REG 0x34
-#define SERIAL_OUT_REG 0x38
-#define SERIAL_IN_REG 0x3C
+/* Indexed registers (through CSR_HCINDEX, CSR_HCDATA) */
+#define HCF_HCI 0x04
+#define HCF_HCS 0x08
+#define HCF_HCC 0x0C
+#define HCF_ARBC 0x10
+#define HCF_ISOC 0x18
+#define HCF_FLTS 0x20
+#define HCF_FLTC 0x24
+#define HCF_PMCC 0x28
+#define HCF_WDC 0x2C
+#define HCF_DIAG 0x30
+#define HCF_SERC 0x34
+#define HCF_SDO 0x38
+#define HCF_SDI 0x3C

-/* Masks for interrupt bits in HC_INT_MASK_REG indexed register */
-#define SERIAL_INT_MASK 0x01
-#define FAULT_INT_MASK 0x02
-#define HCF_INT_MASK 0x04
-#define ALL_INDEXED_INTS_MASK 0x07
+/* Masks for interrupt bits in HCF_HCI indexed register */
+#define HCI_SERIAL_INT_MASK 0x01
+#define HCI_FAULT_INT_MASK 0x02
+#define HCI_HCF_INT_MASK 0x04
+#define HCI_ALL_INTS_MASK 0x07
+
+/* Masks for the bits in the HCF_HCS indexed register */
+#define HCS_HA 0x00000001
+#define HCS_ACTIVE 0x00000002
+#define HCS_RH_STATE 0x00000004
+#define HCS_HARD_RESET 0x00000008
+#define HCS_SOFT_RESET 0x00000010
+#define HCS_RH_ALIVE 0x00000020
+#define HCS_SWITCH_OVER 0x00000040
+#define HCS_TAKEOVER_TYPE 0x00000080
+#define HCS_BUS1_ACTIVE 0x00000100
+#define HCS_BUS2_ACTIVE 0x00000200
+#define HCS_SPLIT_MODE_ERROR 0x00000400
+
+/* CompactPCI bus segment device slot numbers */
+#define BUS1_SLOT 0x08
+#define BUS2_SLOT 0x0C

/* Digital I/O port storing ENUM# */
#define ENUM_PORT 0xE1


Attachments:
deadlock.diff (13.40 kB)

2003-02-06 18:22:22

by Rusty Lynch

[permalink] [raw]
Subject: Re: [PATCH][2.5.59-bk]Sysfs interface for ZT5550 Redundant Host Controller

On Wed, 2003-02-05 at 20:12, Greg KH wrote:
> On Wed, Feb 05, 2003 at 12:48:48PM -0800, Rusty Lynch wrote:
> > Here is a second version of the zt5550 reduncant host controller sysfs
> > interface patch.
>
> I couldnt get this to apply, sorry. Can you rediff it against the
> patches I just sent to Linus?
>
> thanks,
>
> greg k-h

Here is my patch on today's bk tree and Scott's deadlock fix.

--rustyl

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.975 -> 1.976
# drivers/hotplug/cpcihp_zt5550.h 1.2 -> 1.3
# drivers/hotplug/Kconfig 1.5 -> 1.6
# drivers/hotplug/cpcihp_zt5550.c 1.2 -> 1.3
# drivers/hotplug/Makefile 1.13 -> 1.14
# (new) -> 1.1 drivers/hotplug/cpcihp_zt5550_rhc.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/06 [email protected] 1.976
# Adding sysfs interface for the zt5550 redundant host controller
# --------------------------------------------
#
diff -Nru a/drivers/hotplug/Kconfig b/drivers/hotplug/Kconfig
--- a/drivers/hotplug/Kconfig Thu Feb 6 10:29:53 2003
+++ b/drivers/hotplug/Kconfig Thu Feb 6 10:29:53 2003
@@ -101,6 +101,23 @@

When in doubt, say N.

+config HOTPLUG_PCI_CPCI_ZT5550_RHC
+ bool "Ziatech ZT5550 CompactPCI RHC Sysfs Interface"
+ depends on HOTPLUG_PCI_CPCI_ZT5550
+ help
+ Say Y here if you have an Performance Technologies (formerly Intel,
+ formerly just Ziatech) Ziatech ZT5550 CompactPCI system card, and
+ would like to have configuration access to the onboard
+ Redundant Host Controller.
+
+ Saying Y here will cause a new "zt5550_rhc" directory to be created
+ in the root of your sysfs, with a directory for each of the rhc
+ indirect registers created inside the zt5550_rhc directory, and then
+ control files in each of those directorys giving user space access
+ to all of the bits in those indirect registers.
+
+ When in doubt, say N.
+
config HOTPLUG_PCI_CPCI_GENERIC
tristate "Generic port I/O CompactPCI Hotplug driver"
depends on HOTPLUG_PCI_CPCI && X86
diff -Nru a/drivers/hotplug/Makefile b/drivers/hotplug/Makefile
--- a/drivers/hotplug/Makefile Thu Feb 6 10:29:53 2003
+++ b/drivers/hotplug/Makefile Thu Feb 6 10:29:53 2003
@@ -7,6 +7,7 @@
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
+obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC) += cpcihp_zt5550_rhc.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o

pci_hotplug-objs := pci_hotplug_core.o
diff -Nru a/drivers/hotplug/cpcihp_zt5550.c b/drivers/hotplug/cpcihp_zt5550.c
--- a/drivers/hotplug/cpcihp_zt5550.c Thu Feb 6 10:29:53 2003
+++ b/drivers/hotplug/cpcihp_zt5550.c Thu Feb 6 10:29:53 2003
@@ -35,6 +35,8 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <linux/kobject.h>
+#include <linux/bitops.h>
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"

@@ -42,22 +44,6 @@
#define DRIVER_AUTHOR "Scott Murray <[email protected]>"
#define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver"

-#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
-#define MY_NAME "cpcihp_zt5550"
-#else
-#define MY_NAME THIS_MODULE->name
-#endif
-
-#define dbg(format, arg...) \
- do { \
- if(debug) \
- printk (KERN_DEBUG "%s: " format "\n", \
- MY_NAME , ## arg); \
- } while(0)
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
-
/* local variables */
static int debug;
static int poll;
@@ -75,8 +61,8 @@

/* Host controller register addresses */
static void *hc_registers;
-static void *csr_hc_index;
-static void *csr_hc_data;
+void *csr_hc_index;
+void *csr_hc_data;
static void *csr_intstat;
static void *csr_intmask;

@@ -259,12 +245,12 @@
}
dbg("registered controller");

- if(hcf_hcs & HCS_BUS1_ACTIVE) {
+ if(hcf_hcs & HCS_BUS1_ACTIVE_MASK) {
status = zt5550_register_bus(BUS1_SLOT, &bus1_dev, &bus1);
if(status)
goto init_register_error;
}
- if(hcf_hcs & HCS_BUS2_ACTIVE) {
+ if(hcf_hcs & HCS_BUS2_ACTIVE_MASK) {
status = zt5550_register_bus(BUS2_SLOT, &bus2_dev, &bus2);
if(status)
goto init_register_error;
@@ -277,6 +263,7 @@
}
dbg("started cPCI hotplug system");

+
return 0;
init_register_error:
if(bus1)
@@ -318,13 +305,20 @@

static int __init zt5550_init(void)
{
+ int rv;
+
info(DRIVER_DESC " version: " DRIVER_VERSION);
- return pci_module_init(&zt5550_hc_driver);
+ rv = pci_module_init(&zt5550_hc_driver);
+ if (!rv)
+ create_hc_files(csr_hc_index,csr_hc_data,&zt5550_hc_driver);
+
+ return rv;
}

static void __exit
zt5550_exit(void)
{
+ remove_hc_files();
pci_unregister_driver(&zt5550_hc_driver);
release_region(ENUM_PORT, 1);
}
diff -Nru a/drivers/hotplug/cpcihp_zt5550.h b/drivers/hotplug/cpcihp_zt5550.h
--- a/drivers/hotplug/cpcihp_zt5550.h Thu Feb 6 10:29:53 2003
+++ b/drivers/hotplug/cpcihp_zt5550.h Thu Feb 6 10:29:53 2003
@@ -33,6 +33,22 @@
#ifndef _CPCIHP_ZT5550_H
#define _CPCIHP_ZT5550_H

+#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
+#define MY_NAME "cpcihp_zt5550"
+#else
+#define MY_NAME THIS_MODULE->name
+#endif
+
+#define dbg(format, arg...) \
+ do { \
+ if(debug) \
+ printk (KERN_DEBUG "%s: " format "\n", \
+ MY_NAME , ## arg); \
+ } while(0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
+
/* Direct registers */
#define CSR_HCINDEX 0x00
#define CSR_HCDATA 0x04
@@ -44,12 +60,40 @@
#define CSR_TIM0 0x10
#define CSR_TIM1 0x14

+/* Masks for bits in CSR_INTSTAT (interrupt status) direct register */
+#define INTSTAT_SERIAL_FLAG 0x01
+#define INTSTAT_FAULT_FLAG 0x02
+#define INTSTAT_HCS_FLAG 0x04
+#define INTSTAT_TIM0_FLAG 0x08
+#define INTSTAT_TIM1_FLAG 0x10
+#define INTSTAT_ENUM_FLAG 0x20
+
/* Masks for interrupt bits in CSR_INTMASK direct register */
#define INTMASK_TIM0_INT_MASK 0x01
#define INTMASK_TIM1_INT_MASK 0x02
#define INTMASK_ENUM_INT_MASK 0x04
#define INTMASK_ALL_INTS_MASK 0x07

+/* Mask for bits in CSR_ENET (ethernet routing) direct register */
+#define ENET_A_REAR 0x01
+#define ENET_B_ROUTING 0x60
+
+/* Mask for bits in the CSR_T0_C (timer #0 control) direct register */
+#define T0_C_ENABLE 0x0001
+#define T0_C_TIMEOUT_MODE 0x0002
+#define T0_C_CLOCK_SOURCE 0x000c
+#define T0_C_READ_MODE 0x0030
+#define T0_C_WRITE_MODE 0x0040
+#define T0_C_OUTPUT_FLAG 0x0080
+
+/* Mask for bits in the CSR_T1_C (timer #1 control) direct register */
+#define T1_C_ENABLE 0x0001
+#define T1_C_TIMEOUT_MODE 0x0002
+#define T1_C_CLOCK_SOURCE 0x000c
+#define T1_C_READ_MODE 0x0030
+#define T1_C_WRITE_MODE 0x0040
+#define T1_C_OUTPUT_FLAG 0x0080
+
/* Indexed registers (through CSR_HCINDEX, CSR_HCDATA) */
#define HCF_HCI 0x04
#define HCF_HCS 0x08
@@ -65,32 +109,233 @@
#define HCF_SDO 0x38
#define HCF_SDI 0x3C

-/* Masks for interrupt bits in HCF_HCI indexed register */
+/* Masks for interrupt bits in HCF_HCI */
+/* (host controller interrupt) indexed register */
#define HCI_SERIAL_INT_MASK 0x01
#define HCI_FAULT_INT_MASK 0x02
#define HCI_HCF_INT_MASK 0x04
#define HCI_ALL_INTS_MASK 0x07

-/* Masks for the bits in the HCF_HCS indexed register */
-#define HCS_HA 0x00000001
-#define HCS_ACTIVE 0x00000002
-#define HCS_RH_STATE 0x00000004
-#define HCS_HARD_RESET 0x00000008
-#define HCS_SOFT_RESET 0x00000010
-#define HCS_RH_ALIVE 0x00000020
-#define HCS_SWITCH_OVER 0x00000040
-#define HCS_TAKEOVER_TYPE 0x00000080
-#define HCS_BUS1_ACTIVE 0x00000100
-#define HCS_BUS2_ACTIVE 0x00000200
-#define HCS_SPLIT_MODE_ERROR 0x00000400
+/* Masks for the bits in the HCF_HCS */
+/* (host controller status) indexed register */
+#define HCS_HA_MASK 0x00000001
+#define HCS_ACTIVE_MASK 0x00000002
+#define HCS_RH_STATE_MASK 0x00000004
+#define HCS_HARD_RESET_MASK 0x00000008
+#define HCS_SOFT_RESET_MASK 0x00000010
+#define HCS_RH_ALIVE_MASK 0x00000020
+#define HCS_SWITCH_OVER_MASK 0x00000040
+#define HCS_TAKEOVER_TYPE_MASK 0x00000080
+#define HCS_BUS1_ACTIVE_MASK 0x00000100
+#define HCS_BUS2_ACTIVE_MASK 0x00000200
+#define HCS_SPLIT_MODE_ERR_MASK 0x00000400
+
+/* Masks for the bits in the HCF_HCC */
+/* (host controller command) indexed register */
+#define HCC_RESET_MASK 0x00000001
+#define HCC_DIAG_MODE_MASK 0x00000002
+#define HCC_CONFIG_MODE_MASK 0x00000004
+#define HCC_S2_BP_RESET_MASK 0x00000008
+#define HCC_S1_BP_RESET_MASK 0x00000010
+#define HCC_WARM_BOOT_MASK 0x00000020
+#define HCC_INIT_TAKEOVER_MASK 0x00000040
+#define HCC_WD_ENABLE_MASK 0x00000080
+#define HCC_RESET_BH_MASK 0x00000100
+#define HCC_POWER_DOWN_BH_MASK 0x00000200
+#define HCC_BH_S1_RESPONSE_MASK 0x00001000
+#define HCC_AH_S1_RESPONSE_MASK 0x00002000
+
+/* Masks for the bits in the HCF_ARBC */
+/* (arbitration configuration) indexed register */
+#define ARBC_S1_GNT0_MASK 0x00000001
+#define ARBC_S1_GNT1_MASK 0x00000002
+#define ARBC_S1_GNT2_MASK 0x00000004
+#define ARBC_S1_GNT3_MASK 0x00000008
+#define ARBC_S1_GNT4_MASK 0x00000010
+#define ARBC_S1_GNT5_MASK 0x00000020
+#define ARBC_S1_GNT6_MASK 0x00000040
+#define ARBC_S1_GNT7_MASK 0x00000080
+#define ARBC_S2_GNT0_MASK 0x00000100
+#define ARBC_S2_GNT1_MASK 0x00000200
+#define ARBC_S2_GNT2_MASK 0x00000400
+#define ARBC_S2_GNT3_MASK 0x00000800
+#define ARBC_S2_GNT4_MASK 0x00001000
+#define ARBC_S2_GNT5_MASK 0x00002000
+#define ARBC_S2_GNT6_MASK 0x00004000
+#define ARBC_S2_GNT7_MASK 0x00008000
+
+/* Masks for the bits in the HCF_ISOC */
+/* (isolation configuration) indexed register */
+#define ISOC_UNLOCK_MASK 0x00000001
+#define ISOC_S1_BP_RESET_MASK 0x00000002
+#define ISOC_S2_BP_RESET_MASK 0x00000004
+#define ISOC_BP_INTERRUPT_MASK 0x00000008
+#define ISOC_HOSTILE_MASK 0x00000030
+#define ISOC_FRIENDLY_MASK 0x000000c0
+
+/* Masks for the bits in the HCF_FLTS (fault status) indexed register */
+#define FLTS_WD_TIMEOUT_MASK 0x00000001
+#define FLTS_PERR_MASK 0x00000002
+#define FLTS_IOCHK_MASK 0x00000004
+#define FLTS_NMI_MASK 0x00000008
+#define FLTS_B0_SERR_MASK 0x00000010
+#define FLTS_CPUTEMP_MASK 0x00000040
+#define FLTS_POWER_FAIL_MASK 0x00000080
+#define FLTS_EJECT_BH_MASK 0x00000100
+#define FLTS_EJECT_AH_MASK 0x00000200
+
+/* Masks for the bits in the HCF_FLTC (fault configuration) indexed register */
+#define FLTC_WD_TIMEOUT_MASK 0x00000007
+#define FLTC_PERR_MASK 0x00000038
+#define FLTC_IOCHK_MASK 0x000001c0
+#define FLTC_NMI_MASK 0x00000e00
+#define FLTC_B0_SERR_MASK 0x00007000
+#define FLTC_CPUTEMP_MASK 0x001c0000
+#define FLTC_POWER_FAIL_MASK 0x00e00000
+#define FLTC_EJECT_BH_MASK 0x07000000
+#define FLTC_EJECT_AH_MASK 0x38000000
+#define FLTC_SOFT_RESET_MASK 0x40000000
+#define FLTC_HARD_RESET_MASK 0x80000000
+
+/* Masks for the bits in the HCF_PMCC (PMC control) indexed register */
+#define PMCC_PMC1_STATUS_MASK 0x00000001
+#define PMCC_PMC1_COMMAND2_MASK 0x00000002
+#define PMCC_PMC1_COMMAND4_MASK 0x00000004
+#define PMCC_PMC2_STATUS_MASK 0x00000010
+#define PMCC_PMC2_COMMAND2_MASK 0x00000020
+#define PMCC_PMC2_COMMAND4_MASK 0x00000040
+
+/* Masks for the bits in the HCF_WDC (watchdog control) indexed register */
+#define WDC_TERMINAL_COUNT_MASK 0x0000003f
+#define WDC_PRESCALER_MASK 0x000000c0
+
+/* Masks for the bits in the HCF_DIAG (diagnostics command) indexed register */
+#define DIAG_WD_TIMEOUT_MASK 0x00000001
+#define DIAG_PERR_MASK 0x00000002
+#define DIAG_IOCHK_MASK 0x00000004
+#define DIAG_NMI_MASK 0x00000008
+#define DIAG_B0_SERR_MASK 0x00000010
+#define DIAG_CPUTEMP_MASK 0x00000040
+#define DIAG_POWER_FAIL_MASK 0x00000080
+
+/* Masks for the bits in the HCF_SERC (diagnostics command) indexed register */
+#define SERC_DATA_SENT 0x00000001
+#define SERC_DATA_RECIEVED 0x00000002
+#define SERC_SDO_FLAG_ENABLE 0x00000004
+#define SERC_SDI_FLAG_ENABLE 0x00000008
+#define SERC_HCSI_OFF 0x00000010
+#define SERC_FIND_TOKEN 0x00000020

/* CompactPCI bus segment device slot numbers */
#define BUS1_SLOT 0x08
#define BUS2_SLOT 0x0C

+/* I/O port for setting and configuring watchdog timer */
+#define WDT_PORT 0x79
+
+/* Masks for bits written/read from the watchdog timer port */
+#define WDT_TERMINAL_COUNT 0x07
+#define WDT_FIRST_STAGE_ENABLE 0x10
+#define WDT_RESET_ENABLE 0x20
+#define WDT_FIRST_STAGE_MONITOR 0x40
+#define WDT_RESET_MONITOR 0x80
+
/* Digital I/O port storing ENUM# */
#define ENUM_PORT 0xE1
/* Mask to get to the ENUM# bit on the bus */
#define ENUM_MASK 0x40

+#define hcf_read(index, value, csr_hc_index, csr_hc_data) \
+ { \
+ writeb((u8) index, csr_hc_index); \
+ value = readl(csr_hc_data); \
+ dbg("hcf_read(0x%08x, 0x%08x)",index,value); \
+ }
+
+#define hcf_write(index, value, csr_hc_index, csr_hc_data) \
+ { \
+ writeb((u8) index, csr_hc_index); \
+ writel(value, csr_hc_data); \
+ dbg("hcf_write(0x%08x, 0x%08x)",index,value); \
+ }
+
+#define hcf_set_bit(index, bit, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ hcf_write(index, tmp|bit, csr_hc_index, csr_hc_data); \
+ dbg("hcf_set_bit(0x%08x, 0x%08x)",index,bit); \
+ }
+
+#define hcf_clear_bit(index, bit, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ hcf_write(index, tmp & ~bit, csr_hc_index, csr_hc_data); \
+ dbg("hcf_clear_bit(0x%08x, 0x%08x)",index,bit); \
+ }
+
+#define hcf_write_bits(index, mask, request, csr_hc_index, csr_hc_data) \
+ { \
+ int tmp; \
+ dbg("hcf_write_bits(0x%08x, 0x%08x, 0x%08x)", \
+ index,mask,request); \
+ request = request << (generic_ffs(mask) - 1); \
+ request &= mask; \
+ request |= ~mask; \
+ hcf_read(index, tmp, csr_hc_index, csr_hc_data); \
+ tmp |= mask; \
+ tmp &= request; \
+ hcf_write(index, tmp, csr_hc_index, csr_hc_data); \
+ }
+
+#define hcf_read_bits(index, mask, value, csr_hc_index, csr_hc_data) \
+ { \
+ hcf_read(index, value, csr_hc_index, csr_hc_data); \
+ value = (mask&value)>>(generic_ffs(mask) - 1); \
+ dbg("hcf_read_bits(0x%08x, 0x%08x, 0x%08x)", \
+ index,mask,value); \
+ }
+
+#define decl_hc_attribute(_name) \
+static struct rhc_attribute _name##_attr = { \
+ .attr = { .name = __stringify(_name), .mode = 0644 }, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+}
+
+#define decl_hc_kobject(_name) \
+static struct rhc _name##_obj = { \
+ .kobj.name = __stringify(_name), \
+}
+
+
+#define decl_hc_show_function(_name, _index, _mask) \
+static ssize_t _name##_show(struct rhc * p, char * page) \
+{ \
+ int tmp; \
+ hcf_read_bits(_index, _mask, tmp, p->index, p->data); \
+ return sprintf(page,"%d\n", tmp); \
+}
+
+#define decl_hc_store_function(_name, _index, _mask) \
+static ssize_t _name##_store(struct rhc * p, const char * page, size_t count) \
+{ \
+ int request; \
+ if (sscanf(page, "%i", &request)) {\
+ hcf_write_bits(_index, _mask, request, p->index, p->data); \
+ return count; \
+ } \
+ return -EINVAL; \
+}
+
+#ifdef CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC
+extern void create_hc_files(void *,void *,struct pci_driver *);
+extern void remove_hc_files(void);
+#else /* !CONFIG_HOTPLUG_PCI_CPCI_ZT5550_RHC */
+static inline void create_hc_files(void *i,void *d,struct pci_driver *p){}
+static inline void remove_hc_files(void){}
+#endif
+
#endif /* _CPCIHP_ZT5550_H */
+
diff -Nru a/drivers/hotplug/cpcihp_zt5550_rhc.c b/drivers/hotplug/cpcihp_zt5550_rhc.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/hotplug/cpcihp_zt5550_rhc.c Thu Feb 6 10:29:53 2003
@@ -0,0 +1,365 @@
+/*
+ * cpcihp_zt5550.c
+ *
+ * Intel/Ziatech ZT5550 CompactPCI Redundant Host Controller Sysfs Interface
+ *
+ * Copyright 2002 SOMA Networks, Inc.
+ * Copyright 2001 Intel San Luis Obispo
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/kobject.h>
+#include <linux/bitops.h>
+#include "cpci_hotplug.h"
+#include "cpcihp_zt5550.h"
+
+extern int debug;
+extern void *csr_hc_index;
+extern void *csr_hc_data;
+
+struct rhc {
+ void *index;
+ void *data;
+ struct kobject kobj;
+};
+struct rhc_attribute {
+ struct attribute attr;
+ ssize_t (*show) (struct rhc *,char *);
+ ssize_t (*store)(struct rhc *,const char *, size_t);
+};
+
+static ssize_t rhc_attr_show(struct kobject * kobj,
+ struct attribute * attr,
+ char * page)
+{
+ struct rhc * i = container_of(kobj,struct rhc,kobj);
+ struct rhc_attribute * rhc_attr =
+ container_of(attr,struct rhc_attribute,attr);
+
+ return rhc_attr->show ? rhc_attr->show(i,page) : 0;
+}
+
+static ssize_t rhc_attr_store(struct kobject * kobj,
+ struct attribute * attr,
+ const char * page,
+ size_t count)
+{
+ struct rhc * i = container_of(kobj,struct rhc,kobj);
+ struct rhc_attribute * rhc_attr =
+ container_of(attr,struct rhc_attribute,attr);
+
+ return rhc_attr->store ? rhc_attr->store(i,page,count) : 0;
+}
+
+static struct sysfs_ops rhc_sysfs_ops = {
+ .show = rhc_attr_show,
+ .store = rhc_attr_store,
+};
+
+static struct kobj_type rhc_ktype = {
+ .sysfs_ops = &rhc_sysfs_ops
+};
+
+static struct subsystem rhc_subsys = {
+ .kset = {
+ .kobj = { .name = "rhc" },
+ .ktype = &rhc_ktype,
+ }
+};
+
+/**********************************************************************
+ * Host Control Command attributes
+ * NOTE: The HCC register is by default locked. To change any
+ * value, first unlock by writing a '1' to the UNLOCK bit
+ * in the ISOC register.
+ */
+decl_hc_kobject(hcc);
+
+/* Diagnostics Mode Command */
+decl_hc_store_function(diagnostics_mode,HCF_HCC,HCC_DIAG_MODE_MASK);
+decl_hc_show_function(diagnostics_mode,HCF_HCC,HCC_DIAG_MODE_MASK);
+decl_hc_attribute(diagnostics_mode);
+
+/* Reset Backup Host Command*/
+decl_hc_store_function(reset_bh,HCF_HCC,HCC_RESET_BH_MASK);
+decl_hc_show_function(reset_bh,HCF_HCC,HCC_RESET_BH_MASK);
+decl_hc_attribute(reset_bh);
+
+/* Power Down Backup Host Command */
+decl_hc_store_function(power_down_bh,HCF_HCC,HCC_POWER_DOWN_BH_MASK);
+decl_hc_show_function(power_down_bh,HCF_HCC,HCC_POWER_DOWN_BH_MASK);
+decl_hc_attribute(power_down_bh);
+
+/**********************************************************************
+ * Isolation Configuration register (ISOC) attributes
+ */
+decl_hc_kobject(isoc);
+
+/* Hostile Configuration (what happens on a hostile takeover)*/
+decl_hc_store_function(hostile,HCF_ISOC,ISOC_HOSTILE_MASK);
+decl_hc_show_function(hostile,HCF_ISOC,ISOC_HOSTILE_MASK);
+decl_hc_attribute(hostile);
+
+/* Friendly Configuration (what happens on a friendly takeover)*/
+decl_hc_store_function(friendly,HCF_ISOC,ISOC_FRIENDLY_MASK);
+decl_hc_show_function(friendly,HCF_ISOC,ISOC_FRIENDLY_MASK);
+decl_hc_attribute(friendly);
+
+/* HCC Unlock Command */
+decl_hc_store_function(unlock,HCF_ISOC,ISOC_UNLOCK_MASK);
+decl_hc_show_function(unlock,HCF_ISOC,ISOC_UNLOCK_MASK);
+decl_hc_attribute(unlock);
+
+/**********************************************************************
+ * Fault Configuration register (FLTC) attributes
+ */
+decl_hc_kobject(fltc);
+
+/* Watchdog Timeout Configuration */
+decl_hc_store_function(wd_timeout,HCF_FLTC,FLTC_WD_TIMEOUT_MASK);
+decl_hc_show_function(wd_timeout,HCF_FLTC,FLTC_WD_TIMEOUT_MASK);
+decl_hc_attribute(wd_timeout);
+
+/* PERR Configuration */
+decl_hc_store_function(perr,HCF_FLTC,FLTC_PERR_MASK);
+decl_hc_show_function(perr,HCF_FLTC,FLTC_PERR_MASK);
+decl_hc_attribute(perr);
+
+/* IOCHK Configuration */
+decl_hc_store_function(iochk,HCF_FLTC,FLTC_IOCHK_MASK);
+decl_hc_show_function(iochk,HCF_FLTC,FLTC_IOCHK_MASK);
+decl_hc_attribute(iochk);
+
+/* NMI Configuration */
+decl_hc_store_function(nmi,HCF_FLTC,FLTC_NMI_MASK);
+decl_hc_show_function(nmi,HCF_FLTC,FLTC_NMI_MASK);
+decl_hc_attribute(nmi);
+
+/* B0_SERR Configuration */
+decl_hc_store_function(b0_serr,HCF_FLTC,FLTC_B0_SERR_MASK);
+decl_hc_show_function(b0_serr,HCF_FLTC,FLTC_B0_SERR_MASK);
+decl_hc_attribute(b0_serr);
+
+/* CPUTEMP Configuration */
+decl_hc_store_function(cputemp,HCF_FLTC,FLTC_CPUTEMP_MASK);
+decl_hc_show_function(cputemp,HCF_FLTC,FLTC_CPUTEMP_MASK);
+decl_hc_attribute(cputemp);
+
+/* Power Fail Configuration */
+decl_hc_store_function(power_fail,HCF_FLTC,FLTC_POWER_FAIL_MASK);
+decl_hc_show_function(power_fail,HCF_FLTC,FLTC_POWER_FAIL_MASK);
+decl_hc_attribute(power_fail);
+
+/* Eject BH Configuration */
+decl_hc_store_function(eject_bh,HCF_FLTC,FLTC_EJECT_BH_MASK);
+decl_hc_show_function(eject_bh,HCF_FLTC,FLTC_EJECT_BH_MASK);
+decl_hc_attribute(eject_bh);
+
+/* Eject AH Configuration */
+decl_hc_store_function(eject_ah,HCF_FLTC,FLTC_EJECT_AH_MASK);
+decl_hc_show_function(eject_ah,HCF_FLTC,FLTC_EJECT_AH_MASK);
+decl_hc_attribute(eject_ah);
+
+/* Soft Reset Configuration */
+decl_hc_store_function(soft_reset,HCF_FLTC,FLTC_SOFT_RESET_MASK);
+decl_hc_show_function(soft_reset,HCF_FLTC,FLTC_SOFT_RESET_MASK);
+decl_hc_attribute(soft_reset);
+
+/* Hard Reset Configuration */
+decl_hc_store_function(hard_reset,HCF_FLTC,FLTC_HARD_RESET_MASK);
+decl_hc_show_function(hard_reset,HCF_FLTC,FLTC_HARD_RESET_MASK);
+decl_hc_attribute(hard_reset);
+
+/**********************************************************************
+ * Diagnostics (DIAG) register attributes: Setting any of these bits
+ * will cause the associated fault to be simulated.
+ */
+decl_hc_kobject(diag);
+
+/* Watchdog Timeout Diagnostic */
+decl_hc_store_function(diag_wd_timeout,HCF_DIAG,DIAG_WD_TIMEOUT_MASK);
+decl_hc_show_function(diag_wd_timeout,HCF_DIAG,DIAG_WD_TIMEOUT_MASK);
+decl_hc_attribute(diag_wd_timeout);
+
+/* PERR Diagnostic */
+decl_hc_store_function(diag_perr,HCF_DIAG,DIAG_PERR_MASK);
+decl_hc_show_function(diag_perr,HCF_DIAG,DIAG_PERR_MASK);
+decl_hc_attribute(diag_perr);
+
+/* IOCHK Diagnostic */
+decl_hc_store_function(diag_iochk,HCF_DIAG,DIAG_IOCHK_MASK);
+decl_hc_show_function(diag_iochk,HCF_DIAG,DIAG_IOCHK_MASK);
+decl_hc_attribute(diag_iochk);
+
+/* NMI Diagnostic */
+decl_hc_store_function(diag_nmi,HCF_DIAG,DIAG_NMI_MASK);
+decl_hc_show_function(diag_nmi,HCF_DIAG,DIAG_NMI_MASK);
+decl_hc_attribute(diag_nmi);
+
+/* B0 SERR Diagnostic */
+decl_hc_store_function(diag_b0_serr,HCF_DIAG,DIAG_B0_SERR_MASK);
+decl_hc_show_function(diag_b0_serr,HCF_DIAG,DIAG_B0_SERR_MASK);
+decl_hc_attribute(diag_b0_serr);
+
+/* CPUTEMP Diagnostic */
+decl_hc_store_function(diag_cputemp,HCF_DIAG,DIAG_CPUTEMP_MASK);
+decl_hc_show_function(diag_cputemp,HCF_DIAG,DIAG_CPUTEMP_MASK);
+decl_hc_attribute(diag_cputemp);
+
+/* Power Fail Diagnostic */
+decl_hc_store_function(diag_power_fail,HCF_DIAG,DIAG_POWER_FAIL_MASK);
+decl_hc_show_function(diag_power_fail,HCF_DIAG,DIAG_POWER_FAIL_MASK);
+decl_hc_attribute(diag_power_fail);
+
+/**********************************************************************
+ * Watchdog Control (WDC) register attributes
+ */
+decl_hc_kobject(wdc);
+
+/* Watchdog Terminal Count (prescaler counts to timeout) */
+decl_hc_store_function(terminal_count,HCF_WDC,WDC_TERMINAL_COUNT_MASK);
+decl_hc_show_function(terminal_count,HCF_WDC,WDC_TERMINAL_COUNT_MASK);
+decl_hc_attribute(terminal_count);
+
+/* Watchdog Prescaler (clock period) */
+decl_hc_store_function(prescaler,HCF_WDC,WDC_PRESCALER_MASK);
+decl_hc_show_function(prescaler,HCF_WDC,WDC_PRESCALER_MASK);
+decl_hc_attribute(prescaler);
+
+void create_hc_files(void *index, void *data, struct pci_driver *d)
+{
+ if (!index || !data || !d)
+ return;
+
+ rhc_subsys.kset.kobj.parent = &(d->driver.kobj);
+ if(subsystem_register(&rhc_subsys))
+ return;
+
+ /* hcc */
+ hcc_obj.index = index;
+ hcc_obj.data = data;
+ kobj_set_kset_s(&hcc_obj, rhc_subsys);
+ kobject_register(&hcc_obj.kobj);
+ sysfs_create_file(&hcc_obj.kobj, &diagnostics_mode_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &reset_bh_attr.attr);
+ sysfs_create_file(&hcc_obj.kobj, &power_down_bh_attr.attr);
+
+ /* isoc */
+ isoc_obj.index = index;
+ isoc_obj.data = data;
+ kobj_set_kset_s(&isoc_obj, rhc_subsys);
+ kobject_register(&isoc_obj.kobj);
+ sysfs_create_file(&isoc_obj.kobj, &unlock_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &hostile_attr.attr);
+ sysfs_create_file(&isoc_obj.kobj, &friendly_attr.attr);
+
+ /* fltc */
+ fltc_obj.index = index;
+ fltc_obj.data = data;
+ kobj_set_kset_s(&fltc_obj, rhc_subsys);
+ kobject_register(&fltc_obj.kobj);
+ sysfs_create_file(&fltc_obj.kobj, &wd_timeout_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &perr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &iochk_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &nmi_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &b0_serr_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &cputemp_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &power_fail_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_bh_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &eject_ah_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &soft_reset_attr.attr);
+ sysfs_create_file(&fltc_obj.kobj, &hard_reset_attr.attr);
+
+ /* wdc */
+ wdc_obj.index = index;
+ wdc_obj.data = data;
+ kobj_set_kset_s(&wdc_obj, rhc_subsys);
+ kobject_register(&wdc_obj.kobj);
+ sysfs_create_file(&wdc_obj.kobj, &terminal_count_attr.attr);
+ sysfs_create_file(&wdc_obj.kobj, &prescaler_attr.attr);
+
+ /* diag */
+ diag_obj.index = index;
+ diag_obj.data = data;
+ kobj_set_kset_s(&diag_obj, rhc_subsys);
+ kobject_register(&diag_obj.kobj);
+ sysfs_create_file(&diag_obj.kobj, &diag_wd_timeout_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_perr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_iochk_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_nmi_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_b0_serr_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_cputemp_attr.attr);
+ sysfs_create_file(&diag_obj.kobj, &diag_power_fail_attr.attr);
+}
+
+void remove_hc_files(void)
+{
+ /* hcc */
+ sysfs_remove_file(&hcc_obj.kobj, &diagnostics_mode_attr.attr);
+ sysfs_remove_file(&hcc_obj.kobj, &reset_bh_attr.attr);
+ sysfs_remove_file(&hcc_obj.kobj, &power_down_bh_attr.attr);
+ kobject_unregister(&hcc_obj.kobj);
+
+ /* isoc */
+ sysfs_remove_file(&isoc_obj.kobj, &unlock_attr.attr);
+ sysfs_remove_file(&isoc_obj.kobj, &hostile_attr.attr);
+ sysfs_remove_file(&isoc_obj.kobj, &friendly_attr.attr);
+ kobject_unregister(&isoc_obj.kobj);
+
+ /* fltc */
+ sysfs_remove_file(&fltc_obj.kobj, &wd_timeout_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &perr_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &iochk_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &nmi_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &b0_serr_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &cputemp_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &power_fail_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &eject_bh_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &eject_ah_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &soft_reset_attr.attr);
+ sysfs_remove_file(&fltc_obj.kobj, &hard_reset_attr.attr);
+ kobject_unregister(&fltc_obj.kobj);
+
+ /* wdc */
+ sysfs_remove_file(&wdc_obj.kobj, &terminal_count_attr.attr);
+ sysfs_remove_file(&wdc_obj.kobj, &prescaler_attr.attr);
+ kobject_unregister(&wdc_obj.kobj);
+
+ /* diag */
+ sysfs_remove_file(&diag_obj.kobj, &diag_wd_timeout_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_perr_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_iochk_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_nmi_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_b0_serr_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_cputemp_attr.attr);
+ sysfs_remove_file(&diag_obj.kobj, &diag_power_fail_attr.attr);
+ kobject_unregister(&diag_obj.kobj);
+
+ subsystem_unregister(&rhc_subsys);
+}
+


Attachments:
rhc.diff (29.18 kB)