All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] cpqphp 66/100/133MHz PCI-X support for 2.5.65
@ 2003-03-19 11:57 Torben Mathiasen
  2003-03-19 21:30 ` Greg KH
  0 siblings, 1 reply; 3+ messages in thread
From: Torben Mathiasen @ 2003-03-19 11:57 UTC (permalink / raw)
  To: greg; +Cc: linux-kernel, john.cagle, dan.zink

[-- Attachment #1: Type: text/plain, Size: 1143 bytes --]

Hi Greg,

After being put on hold for a while (needed fixes to CCISS driver, etc) I
attached a patch that adds pci-x support to the cpqphp driver in 2.5.65.

Changes:
	Adds 66/100/133MHz PCI-X support.
	Adds support for dynamically chaning frequency and mode.
	Changes code to also blink the power LED when powering down.
	Uses the IRQ from PCI config space if the ROM resource table doesn't 
	provide one (would previously use the same interrupt as the hotplug
	controller which would lead to bad things when trying to update routing
	tables). Dan Zink should have the credit for this fix.
	Changes find_slot() to cpqhp_find_slot().
	Uses sysfs to display speed/freq.
	Some documentation updates.

It seems you're in the middle of updating all hotplug drivers. The cpqphp
driver will oops if you plug in any adapter (unrelated to this patch). I'm sure
you're aware of this so I didn't bother looking into a fix. It happens because
pci_scan_slot() now returns an integer instead of a struct pci_dev*.

A 2.4 version is also done and working as expected (tested with CCISS, nics, etc).
When would you prefer to have that patch?

Thanks,
Torben

[-- Attachment #2: linux-2.5.65-pcix-1.diff --]
[-- Type: text/plain, Size: 19775 bytes --]

diff -urN -X exclude linux-2.5.65/drivers/hotplug/cpqphp.h linux-2.5.65-pcix/drivers/hotplug/cpqphp.h
--- linux-2.5.65/drivers/hotplug/cpqphp.h	Mon Mar 17 15:44:41 2003
+++ linux-2.5.65-pcix/drivers/hotplug/cpqphp.h	Wed Mar 19 06:27:50 2003
@@ -30,7 +30,7 @@
 
 #include "pci_hotplug.h"
 #include <asm/io.h>		/* for read? and write? functions */
-
+#include <linux/delay.h>	/* for delays */
 
 #if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE)
 	#define MY_NAME	"cpqphp.o"
@@ -145,6 +145,10 @@
 	u8	reserved11;		/* 0x2b */
 	u8	slot_SERR;		/* 0x2c */
 	u8	slot_power;		/* 0x2d */
+	u8	reserved12;		/* 0x2e */
+	u8	reserved13;		/* 0x2f */
+	u8	next_curr_freq;		/* 0x30 */
+	u8	reset_freq_mode;	/* 0x31 */
 } __attribute__ ((packed));
 
 /* offsets to the controller registers based on the above structure layout */
@@ -172,6 +176,8 @@
 	CTRL_RESERVED11 =	offsetof(struct ctrl_reg, reserved11),
 	SLOT_SERR =		offsetof(struct ctrl_reg, slot_SERR),
 	SLOT_POWER =		offsetof(struct ctrl_reg, slot_power),
+	NEXT_CURR_FREQ =	offsetof(struct ctrl_reg, next_curr_freq),
+	RESET_FREQ_MODE =	offsetof(struct ctrl_reg, reset_freq_mode),
 };
 
 struct hrt {
@@ -299,6 +305,7 @@
 	struct slot *slot;
 	u8 next_event;
 	u8 interrupt;
+	u8 cfgspc_irq;
 	u8 bus;				/* bus number for the pci hotplug controller */
 	u8 rev;
 	u8 slot_device_offset;
@@ -343,6 +350,7 @@
 #define PCI_SUB_HPC_ID2			0xA2F8
 #define PCI_SUB_HPC_ID3			0xA2F9
 #define PCI_SUB_HPC_ID_INTC		0xA2FA
+#define PCI_SUB_HPC_ID4			0xA2FD
 
 #define INT_BUTTON_IGNORE		0
 #define INT_PRESENCE_ON			1
@@ -435,7 +443,7 @@
 extern void	cpqhp_destroy_resource_list	(struct resource_lists * resources);
 extern int	cpqhp_configure_device		(struct controller* ctrl, struct pci_func* func);
 extern int	cpqhp_unconfigure_device	(struct pci_func* func);
-
+extern struct slot *cpqhp_find_slot		(struct controller *ctrl, u8 device);
 
 /* Global variables */
 extern int cpqhp_debug;
@@ -563,6 +571,7 @@
 	u32 led_control;
 	
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control &= ~(0x0101L << slot);
 	led_control |= (0x0001L << slot);
 	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
 }
@@ -604,14 +613,63 @@
 }
 
 
+/*
+ * get_controller_speed - find the current frequency/mode of controller.
+ *
+ * @ctrl: controller to get frequency/mode for.
+ *
+ * Returns controller speed.
+ *
+ */
 static inline u8 get_controller_speed (struct controller *ctrl)
 {
-	u16 misc;
-	
-	misc = readw(ctrl->hpc_reg + MISC);
-	return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
+	u8 curr_freq;
+ 	u16 misc;
+ 	
+	if (ctrl->pcix_support) {
+		curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
+		if ((curr_freq & 0xB0) == 0xB0) 
+			return PCI_SPEED_133MHz_PCIX;
+		if ((curr_freq & 0xA0) == 0xA0)
+			return PCI_SPEED_100MHz_PCIX;
+		if ((curr_freq & 0x90) == 0x90)
+			return PCI_SPEED_66MHz_PCIX;
+		if (curr_freq & 0x10)
+			return PCI_SPEED_66MHz;
+
+		return PCI_SPEED_33MHz;
+	}
+
+ 	misc = readw(ctrl->hpc_reg + MISC);
+ 	return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
 }
+ 
+
+/*
+ * get_adapter_speed - find the max supported frequency/mode of adapter.
+ *
+ * @ctrl: hotplug controller.
+ * @hp_slot: hotplug slot where adapter is installed.
+ *
+ * Returns adapter speed.
+ *
+ */
+static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot)
+{
+	u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT);
+	dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword);
+	if (ctrl->pcix_support) {
+		if (temp_dword & (0x10000 << hp_slot))
+			return PCI_SPEED_133MHz_PCIX;
+		if (temp_dword & (0x100 << hp_slot))
+			return PCI_SPEED_66MHz_PCIX;
+	}
 
+	if (temp_dword & (0x01 << hp_slot))
+		return PCI_SPEED_66MHz;
+
+	return PCI_SPEED_33MHz;
+}
 
 static inline void enable_slot_power (struct controller *ctrl, u8 slot)
 {
@@ -720,5 +778,138 @@
 	return retval;
 }
 
+
+/**
+ * set_controller_speed - set the frequency and/or mode of a specific
+ * controller segment.
+ *
+ * @ctrl: controller to change frequency/mode for.
+ * @adapter_speed: the speed of the adapter we want to match.
+ * @hp_slot: the slot number where the adapter is installed.
+ *
+ * Returns 0 if we successfully change frequency and/or mode to match the
+ * adapter speed.
+ * 
+ */
+static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
+{
+	struct slot *slot;
+	u8 reg;
+	u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
+	u16 reg16;
+	u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
+	
+	if (ctrl->speed == adapter_speed)
+		return 0;
+	
+	/* We don't allow freq/mode changes if we find another adapter running
+	 * in another slot on this controller */
+	for(slot = ctrl->slot; slot; slot = slot->next) {
+		if (slot->device == (hp_slot + ctrl->slot_device_offset)) 
+			continue;
+		if (!slot->hotplug_slot && !slot->hotplug_slot->info) 
+			continue;
+		if (slot->hotplug_slot->info->adapter_status == 0) 
+			continue;
+		/* If another adapter is running on the same segment but at a
+		 * lower speed/mode, we allow the new adapter to function at
+		 * this rate if supported */
+		if (ctrl->speed < adapter_speed) 
+			return 0;
+
+		return 1;
+	}
+	
+	/* If the controller doesn't support freq/mode changes and the
+	 * controller is running at a higher mode, we bail */
+	if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
+		return 1;
+	
+	/* But we allow the adapter to run at a lower rate if possible */
+	if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
+		return 0;
+
+	/* We try to set the max speed supported by both the adapter and
+	 * controller */
+	if (ctrl->speed_capability < adapter_speed) {
+		if (ctrl->speed == ctrl->speed_capability)
+			return 0;
+		adapter_speed = ctrl->speed_capability;
+	}
+
+	writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
+	writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
+	
+	set_SOGO(ctrl); 
+	wait_for_ctrl_irq(ctrl);
+	
+	if (adapter_speed != PCI_SPEED_133MHz_PCIX)
+		reg = 0xF5;
+	else
+		reg = 0xF4;	
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
+	
+	reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
+	reg16 &= ~0x000F;
+	switch(adapter_speed) {
+		case(PCI_SPEED_133MHz_PCIX): 
+			reg = 0x75;
+			reg16 |= 0xB; 
+			break;
+		case(PCI_SPEED_100MHz_PCIX):
+			reg = 0x74;
+			reg16 |= 0xA;
+			break;
+		case(PCI_SPEED_66MHz_PCIX):
+			reg = 0x73;
+			reg16 |= 0x9;
+			break;
+		case(PCI_SPEED_66MHz):
+			reg = 0x73;
+			reg16 |= 0x1;
+			break;
+		default: /* 33MHz PCI 2.2 */
+			reg = 0x71;
+			break;
+			
+	}
+	reg16 |= 0xB << 12;
+	writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
+	
+	mdelay(5); 
+	
+	/* Reenable interrupts */
+	writel(0, ctrl->hpc_reg + INT_MASK);
+
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 
+	
+	/* Restart state machine */
+	reg = ~0xF;
+	pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
+	pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
+	
+	/* Only if mode change...*/
+	if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
+		((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
+			set_SOGO(ctrl);
+	
+	wait_for_ctrl_irq(ctrl);
+	mdelay(1100);
+	
+	/* Restore LED/Slot state */
+	writel(leds, ctrl->hpc_reg + LED_CONTROL);
+	writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
+	
+	set_SOGO(ctrl);
+	wait_for_ctrl_irq(ctrl);
+
+	ctrl->speed = adapter_speed;
+	slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+	info("Successfully changed frequency/mode for adapter in slot %d\n", 
+			slot->number);
+	return 0;
+}
+
 #endif
 
diff -urN -X exclude linux-2.5.65/drivers/hotplug/cpqphp_core.c linux-2.5.65-pcix/drivers/hotplug/cpqphp_core.c
--- linux-2.5.65/drivers/hotplug/cpqphp_core.c	Mon Mar 17 15:43:37 2003
+++ linux-2.5.65-pcix/drivers/hotplug/cpqphp_core.c	Wed Mar 19 04:41:52 2003
@@ -24,6 +24,9 @@
  *
  * Send feedback to <greg@kroah.com>
  *
+ * Jan 12, 2003 -	Added 66/100/133MHz PCI-X support,
+ * 			Torben Mathiasen <torben.mathiasen@hp.com>
+ *
  */
 
 #include <linux/config.h>
@@ -57,7 +60,7 @@
 static u8 power_mode;
 static int debug;
 
-#define DRIVER_VERSION	"0.9.6"
+#define DRIVER_VERSION	"0.9.7"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC	"Compaq Hot Plug PCI Controller Driver"
 
@@ -835,6 +838,7 @@
 	u8 hp_slot = 0;
 	u8 device;
 	u8 rev;
+	u8 bus_cap;
 	u16 temp_word;
 	u16 vendor_id;
 	u16 subsystem_vid;
@@ -896,6 +900,39 @@
 
 		switch (subsystem_vid) {
 			case PCI_VENDOR_ID_COMPAQ:
+				if (rev >= 0x13) { /* CIOBX */
+					ctrl->push_flag = 1;
+					ctrl->slot_switch_type = 1;		// Switch is present
+					ctrl->push_button = 1;			// Pushbutton is present
+					ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+					ctrl->defeature_PHP = 1;		// PHP is supported
+					ctrl->pcix_support = 1;			// PCI-X supported
+					ctrl->pcix_speed_capability = 1;
+					pci_read_config_byte(pdev, 0x41, &bus_cap);
+					if (bus_cap & 0x80) {
+						dbg("bus max supports 133MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 0x40) {
+						dbg("bus max supports 100MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 20) {
+						dbg("bus max supports 66MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 10) {
+						dbg("bus max supports 66MHz PCI\n");
+						ctrl->speed_capability = PCI_SPEED_66MHz;
+						break;
+					}
+
+					break;
+				}
+
 				switch (subsystem_deviceid) {
 					case PCI_SUB_HPC_ID:
 						/* Original 6500/7000 implementation */
@@ -939,8 +976,18 @@
 						ctrl->pcix_support = 0;			// PCI-X not supported
 						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
 						break;
+					case PCI_SUB_HPC_ID4:
+						/* First PCI-X implementation, 100MHz */
+						ctrl->push_flag = 1;
+						ctrl->slot_switch_type = 1;		// Switch is present
+						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+						ctrl->push_button = 1;			// Pushbutton is present
+						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+						ctrl->defeature_PHP = 1;		// PHP is supported
+						ctrl->pcix_support = 1;			// PCI-X supported
+						ctrl->pcix_speed_capability = 0;	
+						break;
 					default:
-						// TODO: Add SSIDs for CPQ systems that support PCI-X
 						err(msg_HPC_not_supported);
 						rc = -ENODEV;
 						goto err_free_ctrl;
@@ -1029,7 +1076,7 @@
 	info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number);
 
 	dbg ("Hotplug controller capabilities:\n");
-	dbg ("    speed_capability       %s\n", ctrl->speed_capability == PCI_SPEED_33MHz ? "33MHz" : "66Mhz");
+	dbg ("    speed_capability       %d\n", ctrl->speed_capability);
 	dbg ("    slot_switch_type       %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present");
 	dbg ("    defeature_PHP          %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported");
 	dbg ("    alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported");
@@ -1082,7 +1129,6 @@
 	}
 
 	// Check for 66Mhz operation
-	// TODO: Add PCI-X support
 	ctrl->speed = get_controller_speed(ctrl);
 
 
@@ -1119,6 +1165,9 @@
 	// The next line is required for cpqhp_find_available_resources
 	ctrl->interrupt = pdev->irq;
 
+	ctrl->cfgspc_irq = 0;
+	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq);
+
 	rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start);
 	ctrl->add_support = !rc;
 	if (rc) {
diff -urN -X exclude linux-2.5.65/drivers/hotplug/cpqphp_ctrl.c linux-2.5.65-pcix/drivers/hotplug/cpqphp_ctrl.c
--- linux-2.5.65/drivers/hotplug/cpqphp_ctrl.c	Mon Mar 17 15:44:02 2003
+++ linux-2.5.65-pcix/drivers/hotplug/cpqphp_ctrl.c	Wed Mar 19 06:30:47 2003
@@ -136,9 +136,9 @@
 
 
 /*
- * find_slot
+ * cpqhp_find_slot
  */
-static inline struct slot *find_slot (struct controller * ctrl, u8 device)
+struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device)
 {
 	struct slot *slot;
 
@@ -187,7 +187,7 @@
 
 			rc++;
 
-			p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
+			p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
 			if (!p_slot)
 				return 0;
 
@@ -919,6 +919,7 @@
 void cpqhp_ctrl_intr(int IRQ, struct controller * ctrl, struct pt_regs *regs)
 {
 	u8 schedule_flag = 0;
+	u8 reset;
 	u16 misc;
 	u32 Diff;
 	u32 temp_dword;
@@ -970,6 +971,15 @@
 		schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);
 	}
 
+	reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
+	if (reset & 0x40) {
+		/* Bus reset has completed */
+		reset &= 0xCF;
+		writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE);
+		reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
+		wake_up_interruptible(&ctrl->queue);
+	}
+
 	if (schedule_flag) {
 		up(&event_semaphore);
 		dbg("Signal event_semaphore\n");
@@ -1171,6 +1181,7 @@
 {
 	u8 hp_slot;
 	u8 temp_byte;
+	u8 adapter_speed;
 	u32 index;
 	u32 rc = 0;
 	u32 src = 8;
@@ -1188,46 +1199,46 @@
 		//*********************************
 		rc = CARD_FUNCTIONING;
 	} else {
-		if (ctrl->speed == PCI_SPEED_66MHz) {
-			// Wait for exclusive access to hardware
-			down(&ctrl->crit_sect);
-
-			// turn on board without attaching to the bus
-			enable_slot_power (ctrl, hp_slot);
+		// Wait for exclusive access to hardware
+		down(&ctrl->crit_sect);
 
-			set_SOGO(ctrl);
+		// turn on board without attaching to the bus
+		enable_slot_power (ctrl, hp_slot);
 
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
+		set_SOGO(ctrl);
 
-			// Change bits in slot power register to force another shift out
-			// NOTE: this is to work around the timer bug
-			temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
-			writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
-			writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
 
-			set_SOGO(ctrl);
+		// Change bits in slot power register to force another shift out
+		// NOTE: this is to work around the timer bug
+		temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
+		writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
+		writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
 
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
+		set_SOGO(ctrl);
 
-			if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) {
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+		
+		adapter_speed = get_adapter_speed(ctrl, hp_slot);
+		if (ctrl->speed != adapter_speed)
+			if (set_controller_speed(ctrl, adapter_speed, hp_slot))
 				rc = WRONG_BUS_FREQUENCY;
-			}
-			// turn off board without attaching to the bus
-			disable_slot_power (ctrl, hp_slot);
 
-			set_SOGO(ctrl);
+		// turn off board without attaching to the bus
+		disable_slot_power (ctrl, hp_slot);
 
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
+		set_SOGO(ctrl);
 
-			// Done with exclusive hardware access
-			up(&ctrl->crit_sect);
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
 
-			if (rc)
-				return(rc);
-		}
+		// Done with exclusive hardware access
+		up(&ctrl->crit_sect);
+
+		if (rc)
+			return(rc);
 
 		// Wait for exclusive access to hardware
 		down(&ctrl->crit_sect);
@@ -1375,6 +1386,7 @@
 {
 	u8 hp_slot;
 	u8 temp_byte;
+	u8 adapter_speed;
 	int index;
 	u32 temp_register = 0xFFFFFFFF;
 	u32 rc = 0;
@@ -1386,47 +1398,48 @@
 	dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
 	    __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
 
-	if (ctrl->speed == PCI_SPEED_66MHz) {
-		// Wait for exclusive access to hardware
-		down(&ctrl->crit_sect);
-
-		// turn on board without attaching to the bus
-		enable_slot_power (ctrl, hp_slot);
+	// Wait for exclusive access to hardware
+	down(&ctrl->crit_sect);
 
-		set_SOGO(ctrl);
+	// turn on board without attaching to the bus
+	enable_slot_power (ctrl, hp_slot);
 
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
+	set_SOGO(ctrl);
 
-		// Change bits in slot power register to force another shift out
-		// NOTE: this is to work around the timer bug
-		temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
-		writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
-		writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
 
-		set_SOGO(ctrl);
+	// Change bits in slot power register to force another shift out
+	// NOTE: this is to work around the timer bug
+	temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
+	writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
+	writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
 
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
+	set_SOGO(ctrl);
 
-		if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) {
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
+	
+	adapter_speed = get_adapter_speed(ctrl, hp_slot);
+	if (ctrl->speed != adapter_speed)
+		if (set_controller_speed(ctrl, adapter_speed, hp_slot))
 			rc = WRONG_BUS_FREQUENCY;
-		}
-		// turn off board without attaching to the bus
-		disable_slot_power (ctrl, hp_slot);
+	
+	// turn off board without attaching to the bus
+	disable_slot_power (ctrl, hp_slot);
 
-		set_SOGO(ctrl);
+	set_SOGO(ctrl);
 
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
 
-		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
+	// Done with exclusive hardware access
+	up(&ctrl->crit_sect);
 
-		if (rc)
-			return(rc);
-	}
-	p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+	if (rc)
+		return(rc);
+	
+	p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 	// turn on board and blink green LED
 
@@ -1799,7 +1812,7 @@
 				if (!func)
 					return;
 
-				p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+				p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 				if (!p_slot)
 					return;
 
@@ -1859,11 +1872,12 @@
 					}
 					// Wait for exclusive access to hardware
 					down(&ctrl->crit_sect);
-
+					
 					dbg("blink green LED and turn off amber\n");
+					
 					amber_LED_off (ctrl, hp_slot);
 					green_LED_blink (ctrl, hp_slot);
-
+					
 					set_SOGO(ctrl);
 
 					// Wait for SOBS to be unset
@@ -1991,7 +2005,7 @@
 
 	device = func->device;
 	hp_slot = device - ctrl->slot_device_offset;
-	p_slot = find_slot(ctrl, device);
+	p_slot = cpqhp_find_slot(ctrl, device);
 	if (p_slot) {
 		physical_slot = p_slot->number;
 	}
@@ -2090,7 +2104,7 @@
 
 	device = func->device; 
 	func = cpqhp_slot_find(ctrl->bus, device, index++);
-	p_slot = find_slot(ctrl, device);
+	p_slot = cpqhp_find_slot(ctrl, device);
 	if (p_slot) {
 		physical_slot = p_slot->number;
 	}
diff -urN -X exclude linux-2.5.65/drivers/hotplug/cpqphp_pci.c linux-2.5.65-pcix/drivers/hotplug/cpqphp_pci.c
--- linux-2.5.65/drivers/hotplug/cpqphp_pci.c	Mon Mar 17 15:44:44 2003
+++ linux-2.5.65-pcix/drivers/hotplug/cpqphp_pci.c	Wed Mar 19 06:32:09 2003
@@ -97,6 +97,7 @@
 		//this will generate pci_dev structures for all functions, but we will only call this case when lookup fails
 		func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus,
 				 (func->device << 3) + (func->function & 0x7));
+
 		if (func->pci_dev == NULL) {
 			dbg("ERROR: pci_dev still null\n");
 			return 0;
@@ -1209,11 +1210,11 @@
 	temp = 0;
 
 	if (!cpqhp_nic_irq) {
-		cpqhp_nic_irq = ctrl->interrupt;
+		cpqhp_nic_irq = ctrl->cfgspc_irq;
 	}
 
 	if (!cpqhp_disk_irq) {
-		cpqhp_disk_irq = ctrl->interrupt;
+		cpqhp_disk_irq = ctrl->cfgspc_irq;
 	}
 
 	dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] cpqphp 66/100/133MHz PCI-X support for 2.5.65
  2003-03-19 11:57 [PATCH] cpqphp 66/100/133MHz PCI-X support for 2.5.65 Torben Mathiasen
@ 2003-03-19 21:30 ` Greg KH
  2003-03-20 11:32   ` Torben Mathiasen
  0 siblings, 1 reply; 3+ messages in thread
From: Greg KH @ 2003-03-19 21:30 UTC (permalink / raw)
  To: Torben Mathiasen; +Cc: linux-kernel, john.cagle, dan.zink

On Wed, Mar 19, 2003 at 12:57:04PM +0100, Torben Mathiasen wrote:
> Hi Greg,
> 
> After being put on hold for a while (needed fixes to CCISS driver, etc) I
> attached a patch that adds pci-x support to the cpqphp driver in 2.5.65.

Thanks a lot for the patch.  I've added it to my trees and will send it
on to Linus in a few days.

> It seems you're in the middle of updating all hotplug drivers. The cpqphp
> driver will oops if you plug in any adapter (unrelated to this patch). I'm sure
> you're aware of this so I didn't bother looking into a fix. It happens because
> pci_scan_slot() now returns an integer instead of a struct pci_dev*.

Yeah, I'm working on fixing that up right now :(

> A 2.4 version is also done and working as expected (tested with CCISS, nics, etc).
> When would you prefer to have that patch?

I'd be glad to take it now if you have it.

thanks again for the patch,

greg k-h

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] cpqphp 66/100/133MHz PCI-X support for 2.5.65
  2003-03-19 21:30 ` Greg KH
@ 2003-03-20 11:32   ` Torben Mathiasen
  0 siblings, 0 replies; 3+ messages in thread
From: Torben Mathiasen @ 2003-03-20 11:32 UTC (permalink / raw)
  To: Greg KH
  Cc: Torben Mathiasen, linux-kernel, john.cagle, dan.zink, stephen.cameron

[-- Attachment #1: Type: text/plain, Size: 177 bytes --]

On Wed, Mar 19 2003, Greg KH wrote:
> I'd be glad to take it now if you have it.
>

Cool. Its attached. Patch against 2.4.21pre5 but also applies to current BK.

Thanks,
Torben

[-- Attachment #2: linux-2.4.21pre5-pcix-1.diff --]
[-- Type: text/plain, Size: 18690 bytes --]

diff -urN -X exclude linux-2.4.21pre5/drivers/hotplug/cpqphp.h linux-2.4.21pre5-pcix/drivers/hotplug/cpqphp.h
--- linux-2.4.21pre5/drivers/hotplug/cpqphp.h	Thu Nov 28 17:53:12 2002
+++ linux-2.4.21pre5-pcix/drivers/hotplug/cpqphp.h	Wed Mar 19 11:23:32 2003
@@ -30,7 +30,7 @@
 
 #include "pci_hotplug.h"
 #include <asm/io.h>		/* for read? and write? functions */
-
+#include <linux/delay.h>	/* for delays */
 
 #if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE)
 	#define MY_NAME	"cpqphp.o"
@@ -145,6 +145,10 @@
 	u8	reserved11;		/* 0x2b */
 	u8	slot_SERR;		/* 0x2c */
 	u8	slot_power;		/* 0x2d */
+	u8	reserved12;		/* 0x2e */
+	u8	reserved13;		/* 0x2f */
+	u8	next_curr_freq;		/* 0x30 */
+	u8	reset_freq_mode;	/* 0x31 */
 } __attribute__ ((packed));
 
 /* offsets to the controller registers based on the above structure layout */
@@ -172,6 +176,8 @@
 	CTRL_RESERVED11 =	offsetof(struct ctrl_reg, reserved11),
 	SLOT_SERR =		offsetof(struct ctrl_reg, slot_SERR),
 	SLOT_POWER =		offsetof(struct ctrl_reg, slot_power),
+	NEXT_CURR_FREQ =	offsetof(struct ctrl_reg, next_curr_freq),
+	RESET_FREQ_MODE =	offsetof(struct ctrl_reg, reset_freq_mode),
 };
 
 struct hrt {
@@ -345,6 +351,7 @@
 #define PCI_SUB_HPC_ID2			0xA2F8
 #define PCI_SUB_HPC_ID3			0xA2F9
 #define PCI_SUB_HPC_ID_INTC		0xA2FA
+#define PCI_SUB_HPC_ID4			0xA2FD
 
 #define INT_BUTTON_IGNORE		0
 #define INT_PRESENCE_ON			1
@@ -460,6 +467,7 @@
 extern void	cpqhp_destroy_resource_list	(struct resource_lists * resources);
 extern int	cpqhp_configure_device		(struct controller* ctrl, struct pci_func* func);
 extern int	cpqhp_unconfigure_device	(struct pci_func* func);
+extern struct slot *cpqhp_find_slot 		(struct controller *ctrl, u8 device);
 
 
 /* Global variables */
@@ -473,8 +481,6 @@
 
 
 
-/* inline functions */
-
 
 /* Inline functions to check the sanity of a pointer that is passed to us */
 static inline int slot_paranoia_check (struct slot *slot, const char *function)
@@ -588,6 +594,7 @@
 	u32 led_control;
 	
 	led_control = readl(ctrl->hpc_reg + LED_CONTROL);
+	led_control &= ~(0x0101L << slot);
 	led_control |= (0x0001L << slot);
 	writel(led_control, ctrl->hpc_reg + LED_CONTROL);
 }
@@ -629,14 +636,62 @@
 }
 
 
+/*
+ * get_controller_speed - find the current frequency/mode of controller.
+ *
+ * @ctrl: controller to get frequency/mode for.
+ *
+ * Returns controller speed.
+ *
+ */
 static inline u8 get_controller_speed (struct controller *ctrl)
 {
+	u8 curr_freq;
 	u16 misc;
 	
+	if (ctrl->pcix_support) {
+		curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
+		if ((curr_freq & 0xB0) == 0xB0) 
+			return PCI_SPEED_133MHz_PCIX;
+		if ((curr_freq & 0xA0) == 0xA0)
+			return PCI_SPEED_100MHz_PCIX;
+		if ((curr_freq & 0x90) == 0x90)
+			return PCI_SPEED_66MHz_PCIX;
+		if (curr_freq & 0x10)
+			return PCI_SPEED_66MHz;
+
+		return PCI_SPEED_33MHz;
+	}
+
 	misc = readw(ctrl->hpc_reg + MISC);
 	return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
 }
 
+/*
+ * get_adapter_speed - find the max supported frequency/mode of adapter.
+ *
+ * @ctrl: hotplug controller.
+ * @hp_slot: hotplug slot where adapter is installed.
+ *
+ * Returns adapter speed.
+ *
+ */
+static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot)
+{
+	u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT);
+	dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword);
+	if (ctrl->pcix_support) {
+		if (temp_dword & (0x10000 << hp_slot))
+			return PCI_SPEED_133MHz_PCIX;
+		if (temp_dword & (0x100 << hp_slot))
+			return PCI_SPEED_66MHz_PCIX;
+	}
+
+	if (temp_dword & (0x01 << hp_slot))
+		return PCI_SPEED_66MHz;
+
+	return PCI_SPEED_33MHz;
+}
 
 static inline void enable_slot_power (struct controller *ctrl, u8 slot)
 {
@@ -744,5 +799,136 @@
 	return retval;
 }
 
-#endif
+/**
+ * set_controller_speed - set the frequency and/or mode of a specific
+ * controller segment.
+ *
+ * @ctrl: controller to change frequency/mode for.
+ * @adapter_speed: the speed of the adapter we want to match.
+ * @hp_slot: the slot number where the adapter is installed.
+ *
+ * Returns 0 if we successfully change frequency and/or mode to match the
+ * adapter speed.
+ * 
+ */
+static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
+{
+	struct slot *slot;
+	u8 reg;
+	u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
+	u16 reg16;
+	u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
+	
+	if (ctrl->speed == adapter_speed)
+		return 0;
+	
+	/* We don't allow freq/mode changes if we find another adapter running
+	 * in another slot on this controller */
+	for(slot = ctrl->slot; slot; slot = slot->next) {
+		if (slot->device == (hp_slot + ctrl->slot_device_offset)) 
+			continue;
+		if (!slot->hotplug_slot && !slot->hotplug_slot->info) 
+			continue;
+		if (slot->hotplug_slot->info->adapter_status == 0) 
+			continue;
+		/* If another adapter is running on the same segment but at a
+		 * lower speed/mode, we allow the new adapter to function at
+		 * this rate if supported */
+		if (ctrl->speed < adapter_speed) 
+			return 0;
+
+		return 1;
+	}
+	
+	/* If the controller doesn't support freq/mode changes and the
+	 * controller is running at a higher mode, we bail */
+	if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
+		return 1;
+	
+	/* But we allow the adapter to run at a lower rate if possible */
+	if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
+		return 0;
+
+	/* We try to set the max speed supported by both the adapter and
+	 * controller */
+	if (ctrl->speed_capability < adapter_speed) {
+		if (ctrl->speed == ctrl->speed_capability)
+			return 0;
+		adapter_speed = ctrl->speed_capability;
+	}
+
+	writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
+	writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
+	
+	set_SOGO(ctrl); 
+	wait_for_ctrl_irq(ctrl);
+	
+	if (adapter_speed != PCI_SPEED_133MHz_PCIX)
+		reg = 0xF5;
+	else
+		reg = 0xF4;	
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
+	
+	reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
+	reg16 &= ~0x000F;
+	switch(adapter_speed) {
+		case(PCI_SPEED_133MHz_PCIX): 
+			reg = 0x75;
+			reg16 |= 0xB; 
+			break;
+		case(PCI_SPEED_100MHz_PCIX):
+			reg = 0x74;
+			reg16 |= 0xA;
+			break;
+		case(PCI_SPEED_66MHz_PCIX):
+			reg = 0x73;
+			reg16 |= 0x9;
+			break;
+		case(PCI_SPEED_66MHz):
+			reg = 0x73;
+			reg16 |= 0x1;
+			break;
+		default: /* 33MHz PCI 2.2 */
+			reg = 0x71;
+			break;
+			
+	}
+	reg16 |= 0xB << 12;
+	writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
+	
+	mdelay(5); 
+	
+	/* Reenable interrupts */
+	writel(0, ctrl->hpc_reg + INT_MASK);
+
+	pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 
+	
+	/* Restart state machine */
+	reg = ~0xF;
+	pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
+	pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
+	
+	/* Only if mode change...*/
+	if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
+		((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
+			set_SOGO(ctrl);
+	
+	wait_for_ctrl_irq(ctrl);
+	mdelay(1100);
+	
+	/* Restore LED/Slot state */
+	writel(leds, ctrl->hpc_reg + LED_CONTROL);
+	writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
+	
+	set_SOGO(ctrl);
+	wait_for_ctrl_irq(ctrl);
+	
+	ctrl->speed = adapter_speed;
+	slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
+	info("Successfully changed frequency/mode for adapter in slot %d\n", 
+			slot->number);
+	return 0;
+}
+
+#endif
diff -urN -X exclude linux-2.4.21pre5/drivers/hotplug/cpqphp_core.c linux-2.4.21pre5-pcix/drivers/hotplug/cpqphp_core.c
--- linux-2.4.21pre5/drivers/hotplug/cpqphp_core.c	Thu Nov 28 17:53:12 2002
+++ linux-2.4.21pre5-pcix/drivers/hotplug/cpqphp_core.c	Thu Mar 20 05:15:43 2003
@@ -24,6 +24,9 @@
  *
  * Send feedback to <greg@kroah.com>
  *
+ * Jan 12, 2003 -	Added 66/100/133MHz PCI-X support, 
+ * 			Torben Mathiasen <torben.mathiasen@hp.com>
+ *
  */
 
 #include <linux/config.h>
@@ -53,7 +56,7 @@
 static u8 power_mode;
 static int debug;
 
-#define DRIVER_VERSION	"0.9.6"
+#define DRIVER_VERSION	"0.9.7"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC	"Compaq Hot Plug PCI Controller Driver"
 
@@ -829,6 +832,7 @@
 	u8 hp_slot = 0;
 	u8 device;
 	u8 rev;
+	u8 bus_cap;
 	u16 temp_word;
 	u16 vendor_id;
 	u16 subsystem_vid;
@@ -890,6 +894,39 @@
 
 		switch (subsystem_vid) {
 			case PCI_VENDOR_ID_COMPAQ:
+				if (rev >= 0x13) { /* CIOBX */
+					ctrl->push_flag = 1;
+					ctrl->slot_switch_type = 1;		// Switch is present
+					ctrl->push_button = 1;			// Pushbutton is present
+					ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+					ctrl->defeature_PHP = 1;		// PHP is supported
+					ctrl->pcix_support = 1;			// PCI-X supported
+					ctrl->pcix_speed_capability = 1;
+					pci_read_config_byte(pdev, 0x41, &bus_cap);
+					if (bus_cap & 0x80) {
+						dbg("bus max supports 133MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 0x40) {
+						dbg("bus max supports 100MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 20) {
+						dbg("bus max supports 66MHz PCI-X\n");
+						ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
+						break;
+					}
+					if (bus_cap & 10) {
+						dbg("bus max supports 66MHz PCI\n");
+						ctrl->speed_capability = PCI_SPEED_66MHz;
+						break;
+					}
+
+					break;
+				}
+
 				switch (subsystem_deviceid) {
 					case PCI_SUB_HPC_ID:
 						/* Original 6500/7000 implementation */
@@ -933,8 +970,18 @@
 						ctrl->pcix_support = 0;			// PCI-X not supported
 						ctrl->pcix_speed_capability = 0;	// N/A since PCI-X not supported
 						break;
+					case PCI_SUB_HPC_ID4:
+						/* First PCI-X implementation, 100MHz */
+						ctrl->push_flag = 1;
+						ctrl->slot_switch_type = 1;		// Switch is present
+						ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
+						ctrl->push_button = 1;			// Pushbutton is present
+						ctrl->pci_config_space = 1;		// Index/data access to working registers 0 = not supported, 1 = supported
+						ctrl->defeature_PHP = 1;		// PHP is supported
+						ctrl->pcix_support = 1;			// PCI-X supported
+						ctrl->pcix_speed_capability = 0;	
+						break;
 					default:
-						// TODO: Add SSIDs for CPQ systems that support PCI-X
 						err(msg_HPC_not_supported);
 						rc = -ENODEV;
 						goto err_free_ctrl;
@@ -1023,7 +1070,7 @@
 	info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number);
 
 	dbg ("Hotplug controller capabilities:\n");
-	dbg ("    speed_capability       %s\n", ctrl->speed_capability == PCI_SPEED_33MHz ? "33MHz" : "66Mhz");
+	dbg ("    speed_capability       %d\n", ctrl->speed_capability);
 	dbg ("    slot_switch_type       %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present");
 	dbg ("    defeature_PHP          %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported");
 	dbg ("    alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported");
@@ -1066,11 +1113,9 @@
 		goto err_free_mem_region;
 	}
 
-	// Check for 66Mhz operation
-	// TODO: Add PCI-X support
+	// Check for 66Mhz and/or PCI-X operation
 	ctrl->speed = get_controller_speed(ctrl);
-
-
+	
 	//**************************************************
 	//
 	//              Save configuration headers for this and
diff -urN -X exclude linux-2.4.21pre5/drivers/hotplug/cpqphp_ctrl.c linux-2.4.21pre5-pcix/drivers/hotplug/cpqphp_ctrl.c
--- linux-2.4.21pre5/drivers/hotplug/cpqphp_ctrl.c	Thu Nov 28 17:53:12 2002
+++ linux-2.4.21pre5-pcix/drivers/hotplug/cpqphp_ctrl.c	Wed Mar 19 09:28:03 2003
@@ -135,9 +135,9 @@
 
 
 /*
- * find_slot
+ * cpqhp_find_slot
  */
-static inline struct slot *find_slot (struct controller * ctrl, u8 device)
+struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device)
 {
 	struct slot *slot;
 
@@ -186,7 +186,7 @@
 
 			rc++;
 
-			p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
+			p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
 
 			// If the switch closed, must be a button
 			// If not in button mode, nevermind
@@ -916,6 +916,7 @@
 void cpqhp_ctrl_intr(int IRQ, struct controller * ctrl, struct pt_regs *regs)
 {
 	u8 schedule_flag = 0;
+	u8 reset;
 	u16 misc;
 	u32 Diff;
 	u32 temp_dword;
@@ -966,6 +967,15 @@
 		schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl);
 		schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);
 	}
+	
+	reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
+	if (reset & 0x40) {
+		/* Bus Reset has completed */
+		reset &= 0xCF;
+		writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE);
+		reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
+		wake_up_interruptible(&ctrl->queue);
+	}
 
 	if (schedule_flag) {
 		up(&event_semaphore);
@@ -1169,6 +1179,7 @@
 {
 	u8 hp_slot;
 	u8 temp_byte;
+	u8 adapter_speed;
 	u32 index;
 	u32 rc = 0;
 	u32 src = 8;
@@ -1186,46 +1197,47 @@
 		//*********************************
 		rc = CARD_FUNCTIONING;
 	} else {
-		if (ctrl->speed == PCI_SPEED_66MHz) {
-			// Wait for exclusive access to hardware
-			down(&ctrl->crit_sect);
-
-			// turn on board without attaching to the bus
-			enable_slot_power (ctrl, hp_slot);
+		// Wait for exclusive access to hardware
+		down(&ctrl->crit_sect);
 
-			set_SOGO(ctrl);
+		// turn on board without attaching to the bus
+		enable_slot_power (ctrl, hp_slot);
 
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
+		set_SOGO(ctrl);
 
-			// Change bits in slot power register to force another shift out
-			// NOTE: this is to work around the timer bug
-			temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
-			writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
-			writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
 
-			set_SOGO(ctrl);
+		// Change bits in slot power register to force another shift out
+		// NOTE: this is to work around the timer bug
+		temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
+		writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
+		writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
 
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
+		set_SOGO(ctrl);
 
-			if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) {
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
+		
+		// 66MHz and/or PCI-X support check
+		adapter_speed = get_adapter_speed(ctrl, hp_slot);
+		if (ctrl->speed != adapter_speed)
+			if (set_controller_speed(ctrl, adapter_speed, hp_slot))
 				rc = WRONG_BUS_FREQUENCY;
-			}
-			// turn off board without attaching to the bus
-			disable_slot_power (ctrl, hp_slot);
 
-			set_SOGO(ctrl);
+		// turn off board without attaching to the bus
+		disable_slot_power (ctrl, hp_slot);
 
-			// Wait for SOBS to be unset
-			wait_for_ctrl_irq (ctrl);
+		set_SOGO(ctrl);
 
-			// Done with exclusive hardware access
-			up(&ctrl->crit_sect);
+		// Wait for SOBS to be unset
+		wait_for_ctrl_irq (ctrl);
 
-			if (rc)
-				return(rc);
-		}
+		// Done with exclusive hardware access
+		up(&ctrl->crit_sect);
+
+		if (rc)
+			return(rc);
 
 		// Wait for exclusive access to hardware
 		down(&ctrl->crit_sect);
@@ -1373,6 +1385,7 @@
 {
 	u8 hp_slot;
 	u8 temp_byte;
+	u8 adapter_speed;
 	int index;
 	u32 temp_register = 0xFFFFFFFF;
 	u32 rc = 0;
@@ -1383,48 +1396,50 @@
 	hp_slot = func->device - ctrl->slot_device_offset;
 	dbg(__FUNCTION__": func->device, slot_offset, hp_slot = %d, %d ,%d\n",
 	    func->device, ctrl->slot_device_offset, hp_slot);
+	
+	// Wait for exclusive access to hardware
+	down(&ctrl->crit_sect);
 
-	if (ctrl->speed == PCI_SPEED_66MHz) {
-		// Wait for exclusive access to hardware
-		down(&ctrl->crit_sect);
-
-		// turn on board without attaching to the bus
-		enable_slot_power (ctrl, hp_slot);
-
-		set_SOGO(ctrl);
+	// turn on board without attaching to the bus
+	enable_slot_power (ctrl, hp_slot);
 
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
+	set_SOGO(ctrl);
 
-		// Change bits in slot power register to force another shift out
-		// NOTE: this is to work around the timer bug
-		temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
-		writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
-		writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
 
-		set_SOGO(ctrl);
+	// Change bits in slot power register to force another shift out
+	// NOTE: this is to work around the timer bug
+	temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
+	writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
+	writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
 
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
+	set_SOGO(ctrl);
 
-		if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) {
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
+	
+	// 66MHz and/or PCI-X support check
+	adapter_speed = get_adapter_speed(ctrl, hp_slot);
+	if (ctrl->speed != adapter_speed)
+		if (set_controller_speed(ctrl, adapter_speed, hp_slot))
 			rc = WRONG_BUS_FREQUENCY;
-		}
-		// turn off board without attaching to the bus
-		disable_slot_power (ctrl, hp_slot);
+	
+	// turn off board without attaching to the bus
+	disable_slot_power (ctrl, hp_slot);
 
-		set_SOGO(ctrl);
+	set_SOGO(ctrl);
 
-		// Wait for SOBS to be unset
-		wait_for_ctrl_irq (ctrl);
+	// Wait for SOBS to be unset
+	wait_for_ctrl_irq (ctrl);
 
-		// Done with exclusive hardware access
-		up(&ctrl->crit_sect);
+	// Done with exclusive hardware access
+	up(&ctrl->crit_sect);
 
-		if (rc)
-			return(rc);
-	}
-	p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+	if (rc)
+		return(rc);
+	
+	p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 	// turn on board and blink green LED
 
@@ -1800,7 +1815,7 @@
 
 				func = cpqhp_slot_find(ctrl->bus, (hp_slot + ctrl->slot_device_offset), 0);
 
-				p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+				p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
 				dbg("hp_slot %d, func %p, p_slot %p\n",
 				    hp_slot, func, p_slot);
@@ -1990,7 +2005,7 @@
 
 	device = func->device;
 	hp_slot = device - ctrl->slot_device_offset;
-	p_slot = find_slot(ctrl, device);
+	p_slot = cpqhp_find_slot(ctrl, device);
 	if (p_slot) {
 		physical_slot = p_slot->number;
 	}
@@ -2087,7 +2102,7 @@
 
 	device = func->device; 
 	func = cpqhp_slot_find(ctrl->bus, device, index++);
-	p_slot = find_slot(ctrl, device);
+	p_slot = cpqhp_find_slot(ctrl, device);
 	if (p_slot) {
 		physical_slot = p_slot->number;
 	}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-03-20 11:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-03-19 11:57 [PATCH] cpqphp 66/100/133MHz PCI-X support for 2.5.65 Torben Mathiasen
2003-03-19 21:30 ` Greg KH
2003-03-20 11:32   ` Torben Mathiasen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.