pciehp.h 8.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * PCI Express Hot Plug Controller Driver
 *
 * Copyright (C) 1995,2001 Compaq Computer Corporation
 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
 * Copyright (C) 2001 IBM Corp.
 * Copyright (C) 2003-2004 Intel Corporation
 *
 * All rights reserved.
 *
 * 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 program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * 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.
 *
26
 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
L
Linus Torvalds 已提交
27 28 29 30 31 32 33 34
 *
 */
#ifndef _PCIEHP_H
#define _PCIEHP_H

#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
35
#include <linux/sched.h>		/* signal_pending() */
L
Linus Torvalds 已提交
36 37 38 39 40 41 42 43
#include <linux/pcieport_if.h>
#include "pci_hotplug.h"

#define MY_NAME	"pciehp"

extern int pciehp_poll_mode;
extern int pciehp_poll_time;
extern int pciehp_debug;
44
extern int pciehp_force;
L
Linus Torvalds 已提交
45 46 47 48 49 50 51

/*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
#define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)

52 53 54 55 56 57 58
struct hotplug_params {
	u8 cache_line_size;
	u8 latency_timer;
	u8 enable_serr;
	u8 enable_perr;
};

L
Linus Torvalds 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
struct slot {
	struct slot *next;
	u8 bus;
	u8 device;
	u32 number;
	u8 state;
	struct timer_list task_event;
	u8 hp_slot;
	struct controller *ctrl;
	struct hpc_ops *hpc_ops;
	struct hotplug_slot *hotplug_slot;
	struct list_head	slot_list;
};

struct event_info {
	u32 event_type;
	u8 hp_slot;
};

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);

struct php_ctlr_state_s {
	struct php_ctlr_state_s *pnext;
	struct pci_dev *pci_dev;
	unsigned int irq;
	unsigned long flags;				/* spinlock's */
	u32 slot_device_offset;
	u32 num_slots;
    	struct timer_list	int_poll_timer;		/* Added for poll event */
	php_intr_callback_t 	attention_button_callback;
	php_intr_callback_t 	switch_change_callback;
	php_intr_callback_t 	presence_change_callback;
	php_intr_callback_t 	power_fault_callback;
	void 			*callback_instance_id;
	struct ctrl_reg 	*creg;				/* Ptr to controller register space */
};

#define MAX_EVENTS		10
L
Linus Torvalds 已提交
97 98 99
struct controller {
	struct controller *next;
	struct semaphore crit_sect;	/* critical section semaphore */
100
	struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
L
Linus Torvalds 已提交
101 102 103 104
	int num_slots;			/* Number of slots on ctlr */
	int slot_num_inc;		/* 1 or -1 */
	struct pci_dev *pci_dev;
	struct pci_bus *pci_bus;
105
	struct event_info event_queue[MAX_EVENTS];
L
Linus Torvalds 已提交
106 107 108 109 110 111 112 113 114 115 116 117
	struct slot *slot;
	struct hpc_ops *hpc_ops;
	wait_queue_head_t queue;	/* sleep & wake process */
	u8 next_event;
	u8 bus;
	u8 device;
	u8 function;
	u8 slot_device_offset;
	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
	u8 ctrlcap;
	u16 vendor_id;
118
	u8 cap_base;
L
Linus Torvalds 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
};

#define INT_BUTTON_IGNORE		0
#define INT_PRESENCE_ON			1
#define INT_PRESENCE_OFF		2
#define INT_SWITCH_CLOSE		3
#define INT_SWITCH_OPEN			4
#define INT_POWER_FAULT			5
#define INT_POWER_FAULT_CLEAR		6
#define INT_BUTTON_PRESS		7
#define INT_BUTTON_RELEASE		8
#define INT_BUTTON_CANCEL		9

#define STATIC_STATE			0
#define BLINKINGON_STATE		1
#define BLINKINGOFF_STATE		2
#define POWERON_STATE			3
#define POWEROFF_STATE			4

#define PCI_TO_PCI_BRIDGE_CLASS		0x00060400

/* Error messages */
#define INTERLOCK_OPEN			0x00000002
#define ADD_NOT_SUPPORTED		0x00000003
#define CARD_FUNCTIONING		0x00000005
#define ADAPTER_NOT_SAME		0x00000006
#define NO_ADAPTER_PRESENT		0x00000009
#define NOT_ENOUGH_RESOURCES		0x0000000B
#define DEVICE_TYPE_NOT_SUPPORTED	0x0000000C
#define WRONG_BUS_FREQUENCY		0x0000000D
#define POWER_FAILURE			0x0000000E

#define REMOVE_NOT_SUPPORTED		0x00000003

#define DISABLE_CARD			1

/* Field definitions in Slot Capabilities Register */
#define ATTN_BUTTN_PRSN	0x00000001
#define	PWR_CTRL_PRSN	0x00000002
#define MRL_SENS_PRSN	0x00000004
#define ATTN_LED_PRSN	0x00000008
#define PWR_LED_PRSN	0x00000010
#define HP_SUPR_RM_SUP	0x00000020

#define ATTN_BUTTN(cap)		(cap & ATTN_BUTTN_PRSN)
#define POWER_CTRL(cap)		(cap & PWR_CTRL_PRSN)
#define MRL_SENS(cap)		(cap & MRL_SENS_PRSN)
#define ATTN_LED(cap)		(cap & ATTN_LED_PRSN)
#define PWR_LED(cap)		(cap & PWR_LED_PRSN) 
#define HP_SUPR_RM(cap)		(cap & HP_SUPR_RM_SUP)

/*
 * error Messages
 */
#define msg_initialization_err	"Initialization failure, error=%d\n"
#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
#define msg_button_ignore	"PCI slot #%d - button press ignored.  (action in progress...)\n"

/* controller functions */
extern int	pciehp_event_start_thread	(void);
extern void	pciehp_event_stop_thread	(void);
extern int	pciehp_enable_slot		(struct slot *slot);
extern int	pciehp_disable_slot		(struct slot *slot);

extern u8	pciehp_handle_attention_button	(u8 hp_slot, void *inst_id);
extern u8	pciehp_handle_switch_change	(u8 hp_slot, void *inst_id);
extern u8	pciehp_handle_presence_change	(u8 hp_slot, void *inst_id);
extern u8	pciehp_handle_power_fault	(u8 hp_slot, void *inst_id);
/* extern void	long_delay (int delay); */

/* pci functions */
192 193
extern int	pciehp_configure_device		(struct slot *p_slot);
extern int	pciehp_unconfigure_device	(struct slot *p_slot);
R
Rajesh Shah 已提交
194 195
extern int	pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
extern void	pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
196 197
	       	struct hotplug_params *hpp);

L
Linus Torvalds 已提交
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246


/* Global variables */
extern struct controller *pciehp_ctrl_list;

/* Inline functions */

static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{
	struct slot *p_slot, *tmp_slot = NULL;

	p_slot = ctrl->slot;

	while (p_slot && (p_slot->device != device)) {
		tmp_slot = p_slot;
		p_slot = p_slot->next;
	}
	if (p_slot == NULL) {
		err("ERROR: pciehp_find_slot device=0x%x\n", device);
		p_slot = tmp_slot;
	}

	return p_slot;
}

static inline int wait_for_ctrl_irq(struct controller *ctrl)
{
	int retval = 0;

	DECLARE_WAITQUEUE(wait, current);

	add_wait_queue(&ctrl->queue, &wait);
	if (!pciehp_poll_mode)
		/* Sleep for up to 1 second */
		msleep_interruptible(1000);
	else
		msleep_interruptible(2500);
	
	remove_wait_queue(&ctrl->queue, &wait);
	if (signal_pending(current))
		retval =  -EINTR;

	return retval;
}

#define SLOT_NAME_SIZE 10

static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
{
247
	snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number);
L
Linus Torvalds 已提交
248 249 250 251 252 253 254 255
}

enum php_ctlr_type {
	PCI,
	ISA,
	ACPI
};

256
int pcie_init(struct controller *ctrl, struct pcie_device *dev);
L
Linus Torvalds 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288

/* This has no meaning for PCI Express, as there is only 1 slot per port */
int pcie_get_ctlr_slot_config(struct controller *ctrl,
		int *num_ctlr_slots,
		int *first_device_num,
		int *physical_slot_num,
		u8 *ctrlcap);

struct hpc_ops {
	int	(*power_on_slot)	(struct slot *slot);
	int	(*power_off_slot)	(struct slot *slot);
	int	(*get_power_status)	(struct slot *slot, u8 *status);
	int	(*get_attention_status)	(struct slot *slot, u8 *status);
	int	(*set_attention_status)	(struct slot *slot, u8 status);
	int	(*get_latch_status)	(struct slot *slot, u8 *status);
	int	(*get_adapter_status)	(struct slot *slot, u8 *status);

	int	(*get_max_bus_speed)	(struct slot *slot, enum pci_bus_speed *speed);
	int	(*get_cur_bus_speed)	(struct slot *slot, enum pci_bus_speed *speed);

	int	(*get_max_lnk_width)	(struct slot *slot, enum pcie_link_width *value);
	int	(*get_cur_lnk_width)	(struct slot *slot, enum pcie_link_width *value);
	
	int	(*query_power_fault)	(struct slot *slot);
	void	(*green_led_on)		(struct slot *slot);
	void	(*green_led_off)	(struct slot *slot);
	void	(*green_led_blink)	(struct slot *slot);
	void	(*release_ctlr)		(struct controller *ctrl);
	int	(*check_lnk_status)	(struct controller *ctrl);
};

#endif				/* _PCIEHP_H */