ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / pci / hotplug / cpqphp.h
1 /*
2  * Compaq Hot Plug Controller Driver
3  *
4  * Copyright (C) 1995,2001 Compaq Computer Corporation
5  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001 IBM
7  *
8  * All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
18  * NON INFRINGEMENT.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * Send feedback to <greg@kroah.com>
26  *
27  */
28 #ifndef _CPQPHP_H
29 #define _CPQPHP_H
30
31 #include "pci_hotplug.h"
32 #include <linux/interrupt.h>
33 #include <asm/io.h>             /* for read? and write? functions */
34 #include <linux/delay.h>        /* for delays */
35
36 #if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE)
37         #define MY_NAME "cpqphp.o"
38 #else
39         #define MY_NAME THIS_MODULE->name
40 #endif
41
42 #define dbg(fmt, arg...) do { if (cpqhp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
43 #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
44 #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
45 #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
46
47
48
49 struct smbios_system_slot {
50         u8 type;
51         u8 length;
52         u16 handle;
53         u8 name_string_num;
54         u8 slot_type;
55         u8 slot_width;
56         u8 slot_current_usage;
57         u8 slot_length;
58         u16 slot_number;
59         u8 properties1;
60         u8 properties2;
61 } __attribute__ ((packed));
62
63 /* offsets to the smbios generic type based on the above structure layout */
64 enum smbios_system_slot_offsets {
65         SMBIOS_SLOT_GENERIC_TYPE =      offsetof(struct smbios_system_slot, type),
66         SMBIOS_SLOT_GENERIC_LENGTH =    offsetof(struct smbios_system_slot, length),
67         SMBIOS_SLOT_GENERIC_HANDLE =    offsetof(struct smbios_system_slot, handle),
68         SMBIOS_SLOT_NAME_STRING_NUM =   offsetof(struct smbios_system_slot, name_string_num),
69         SMBIOS_SLOT_TYPE =              offsetof(struct smbios_system_slot, slot_type),
70         SMBIOS_SLOT_WIDTH =             offsetof(struct smbios_system_slot, slot_width),
71         SMBIOS_SLOT_CURRENT_USAGE =     offsetof(struct smbios_system_slot, slot_current_usage),
72         SMBIOS_SLOT_LENGTH =            offsetof(struct smbios_system_slot, slot_length),
73         SMBIOS_SLOT_NUMBER =            offsetof(struct smbios_system_slot, slot_number),
74         SMBIOS_SLOT_PROPERTIES1 =       offsetof(struct smbios_system_slot, properties1),
75         SMBIOS_SLOT_PROPERTIES2 =       offsetof(struct smbios_system_slot, properties2),
76 };
77
78 struct smbios_generic {
79         u8 type;
80         u8 length;
81         u16 handle;
82 } __attribute__ ((packed));
83
84 /* offsets to the smbios generic type based on the above structure layout */
85 enum smbios_generic_offsets {
86         SMBIOS_GENERIC_TYPE =   offsetof(struct smbios_generic, type),
87         SMBIOS_GENERIC_LENGTH = offsetof(struct smbios_generic, length),
88         SMBIOS_GENERIC_HANDLE = offsetof(struct smbios_generic, handle),
89 };
90
91 struct smbios_entry_point {
92         char anchor[4];
93         u8 ep_checksum;
94         u8 ep_length;
95         u8 major_version;
96         u8 minor_version;
97         u16 max_size_entry;
98         u8 ep_rev;
99         u8 reserved[5];
100         char int_anchor[5];
101         u8 int_checksum;
102         u16 st_length;
103         u32 st_address;
104         u16 number_of_entrys;
105         u8 bcd_rev;
106 } __attribute__ ((packed));
107
108 /* offsets to the smbios entry point based on the above structure layout */
109 enum smbios_entry_point_offsets {
110         ANCHOR =                offsetof(struct smbios_entry_point, anchor[0]),
111         EP_CHECKSUM =           offsetof(struct smbios_entry_point, ep_checksum),
112         EP_LENGTH =             offsetof(struct smbios_entry_point, ep_length),
113         MAJOR_VERSION =         offsetof(struct smbios_entry_point, major_version),
114         MINOR_VERSION =         offsetof(struct smbios_entry_point, minor_version),
115         MAX_SIZE_ENTRY =        offsetof(struct smbios_entry_point, max_size_entry),
116         EP_REV =                offsetof(struct smbios_entry_point, ep_rev),
117         INT_ANCHOR =            offsetof(struct smbios_entry_point, int_anchor[0]),
118         INT_CHECKSUM =          offsetof(struct smbios_entry_point, int_checksum),
119         ST_LENGTH =             offsetof(struct smbios_entry_point, st_length),
120         ST_ADDRESS =            offsetof(struct smbios_entry_point, st_address),
121         NUMBER_OF_ENTRYS =      offsetof(struct smbios_entry_point, number_of_entrys),
122         BCD_REV =               offsetof(struct smbios_entry_point, bcd_rev),
123 };
124
125 struct ctrl_reg {                       /* offset */
126         u8      slot_RST;               /* 0x00 */
127         u8      slot_enable;            /* 0x01 */
128         u16     misc;                   /* 0x02 */
129         u32     led_control;            /* 0x04 */
130         u32     int_input_clear;        /* 0x08 */
131         u32     int_mask;               /* 0x0a */
132         u8      reserved0;              /* 0x10 */
133         u8      reserved1;              /* 0x11 */
134         u8      reserved2;              /* 0x12 */
135         u8      gen_output_AB;          /* 0x13 */
136         u32     non_int_input;          /* 0x14 */
137         u32     reserved3;              /* 0x18 */
138         u32     reserved4;              /* 0x1a */
139         u32     reserved5;              /* 0x20 */
140         u8      reserved6;              /* 0x24 */
141         u8      reserved7;              /* 0x25 */
142         u16     reserved8;              /* 0x26 */
143         u8      slot_mask;              /* 0x28 */
144         u8      reserved9;              /* 0x29 */
145         u8      reserved10;             /* 0x2a */
146         u8      reserved11;             /* 0x2b */
147         u8      slot_SERR;              /* 0x2c */
148         u8      slot_power;             /* 0x2d */
149         u8      reserved12;             /* 0x2e */
150         u8      reserved13;             /* 0x2f */
151         u8      next_curr_freq;         /* 0x30 */
152         u8      reset_freq_mode;        /* 0x31 */
153 } __attribute__ ((packed));
154
155 /* offsets to the controller registers based on the above structure layout */
156 enum ctrl_offsets {
157         SLOT_RST =              offsetof(struct ctrl_reg, slot_RST),
158         SLOT_ENABLE =           offsetof(struct ctrl_reg, slot_enable),
159         MISC =                  offsetof(struct ctrl_reg, misc),
160         LED_CONTROL =           offsetof(struct ctrl_reg, led_control),
161         INT_INPUT_CLEAR =       offsetof(struct ctrl_reg, int_input_clear),
162         INT_MASK =              offsetof(struct ctrl_reg, int_mask),
163         CTRL_RESERVED0 =        offsetof(struct ctrl_reg, reserved0),
164         CTRL_RESERVED1 =        offsetof(struct ctrl_reg, reserved1),
165         CTRL_RESERVED2 =        offsetof(struct ctrl_reg, reserved1),
166         GEN_OUTPUT_AB =         offsetof(struct ctrl_reg, gen_output_AB),
167         NON_INT_INPUT =         offsetof(struct ctrl_reg, non_int_input),
168         CTRL_RESERVED3 =        offsetof(struct ctrl_reg, reserved3),
169         CTRL_RESERVED4 =        offsetof(struct ctrl_reg, reserved4),
170         CTRL_RESERVED5 =        offsetof(struct ctrl_reg, reserved5),
171         CTRL_RESERVED6 =        offsetof(struct ctrl_reg, reserved6),
172         CTRL_RESERVED7 =        offsetof(struct ctrl_reg, reserved7),
173         CTRL_RESERVED8 =        offsetof(struct ctrl_reg, reserved8),
174         SLOT_MASK =             offsetof(struct ctrl_reg, slot_mask),
175         CTRL_RESERVED9 =        offsetof(struct ctrl_reg, reserved9),
176         CTRL_RESERVED10 =       offsetof(struct ctrl_reg, reserved10),
177         CTRL_RESERVED11 =       offsetof(struct ctrl_reg, reserved11),
178         SLOT_SERR =             offsetof(struct ctrl_reg, slot_SERR),
179         SLOT_POWER =            offsetof(struct ctrl_reg, slot_power),
180         NEXT_CURR_FREQ =        offsetof(struct ctrl_reg, next_curr_freq),
181         RESET_FREQ_MODE =       offsetof(struct ctrl_reg, reset_freq_mode),
182 };
183
184 struct hrt {
185         char sig0;
186         char sig1;
187         char sig2;
188         char sig3;
189         u16 unused_IRQ;
190         u16 PCIIRQ;
191         u8 number_of_entries;
192         u8 revision;
193         u16 reserved1;
194         u32 reserved2;
195 } __attribute__ ((packed));
196
197 /* offsets to the hotplug resource table registers based on the above structure layout */
198 enum hrt_offsets {
199         SIG0 =                  offsetof(struct hrt, sig0),
200         SIG1 =                  offsetof(struct hrt, sig1),
201         SIG2 =                  offsetof(struct hrt, sig2),
202         SIG3 =                  offsetof(struct hrt, sig3),
203         UNUSED_IRQ =            offsetof(struct hrt, unused_IRQ),
204         PCIIRQ =                offsetof(struct hrt, PCIIRQ),
205         NUMBER_OF_ENTRIES =     offsetof(struct hrt, number_of_entries),
206         REVISION =              offsetof(struct hrt, revision),
207         HRT_RESERVED1 =         offsetof(struct hrt, reserved1),
208         HRT_RESERVED2 =         offsetof(struct hrt, reserved2),
209 };
210
211 struct slot_rt {
212         u8 dev_func;
213         u8 primary_bus;
214         u8 secondary_bus;
215         u8 max_bus;
216         u16 io_base;
217         u16 io_length;
218         u16 mem_base;
219         u16 mem_length;
220         u16 pre_mem_base;
221         u16 pre_mem_length;
222 } __attribute__ ((packed));
223
224 /* offsets to the hotplug slot resource table registers based on the above structure layout */
225 enum slot_rt_offsets {
226         DEV_FUNC =              offsetof(struct slot_rt, dev_func),
227         PRIMARY_BUS =           offsetof(struct slot_rt, primary_bus),
228         SECONDARY_BUS =         offsetof(struct slot_rt, secondary_bus),
229         MAX_BUS =               offsetof(struct slot_rt, max_bus),
230         IO_BASE =               offsetof(struct slot_rt, io_base),
231         IO_LENGTH =             offsetof(struct slot_rt, io_length),
232         MEM_BASE =              offsetof(struct slot_rt, mem_base),
233         MEM_LENGTH =            offsetof(struct slot_rt, mem_length),
234         PRE_MEM_BASE =          offsetof(struct slot_rt, pre_mem_base),
235         PRE_MEM_LENGTH =        offsetof(struct slot_rt, pre_mem_length),
236 };
237
238 struct pci_func {
239         struct pci_func *next;
240         u8 bus;
241         u8 device;
242         u8 function;
243         u8 is_a_board;
244         u16 status;
245         u8 configured;
246         u8 switch_save;
247         u8 presence_save;
248         u32 base_length[0x06];
249         u8 base_type[0x06];
250         u16 reserved2;
251         u32 config_space[0x20];
252         struct pci_resource *mem_head;
253         struct pci_resource *p_mem_head;
254         struct pci_resource *io_head;
255         struct pci_resource *bus_head;
256         struct timer_list *p_task_event;
257         struct pci_dev* pci_dev;
258 };
259
260 #define SLOT_MAGIC      0x67267321
261 struct slot {
262         u32 magic;
263         struct slot *next;
264         u8 bus;
265         u8 device;
266         u8 number;
267         u8 is_a_board;
268         u8 configured;
269         u8 state;
270         u8 switch_save;
271         u8 presence_save;
272         u32 capabilities;
273         u16 reserved2;
274         struct timer_list task_event;
275         u8 hp_slot;
276         struct controller *ctrl;
277         void *p_sm_slot;
278         struct hotplug_slot *hotplug_slot;
279 };
280
281 struct pci_resource {
282         struct pci_resource * next;
283         u32 base;
284         u32 length;
285 };
286
287 struct event_info {
288         u32 event_type;
289         u8 hp_slot;
290 };
291
292 struct controller {
293         struct controller *next;
294         u32 ctrl_int_comp;
295         struct semaphore crit_sect;     /* critical section semaphore */
296         void *hpc_reg;                  /* cookie for our pci controller location */
297         struct pci_resource *mem_head;
298         struct pci_resource *p_mem_head;
299         struct pci_resource *io_head;
300         struct pci_resource *bus_head;
301         struct pci_dev *pci_dev;
302         struct pci_bus *pci_bus;
303         struct event_info event_queue[10];
304         struct slot *slot;
305         u8 next_event;
306         u8 interrupt;
307         u8 cfgspc_irq;
308         u8 bus;                         /* bus number for the pci hotplug controller */
309         u8 rev;
310         u8 slot_device_offset;
311         u8 first_slot;
312         u8 add_support;
313         u8 push_flag;
314         enum pci_bus_speed speed;
315         enum pci_bus_speed speed_capability;
316         u8 push_button;                 /* 0 = no pushbutton, 1 = pushbutton present */
317         u8 slot_switch_type;            /* 0 = no switch, 1 = switch present */
318         u8 defeature_PHP;               /* 0 = PHP not supported, 1 = PHP supported */
319         u8 alternate_base_address;      /* 0 = not supported, 1 = supported */
320         u8 pci_config_space;            /* Index/data access to working registers 0 = not supported, 1 = supported */
321         u8 pcix_speed_capability;       /* PCI-X */
322         u8 pcix_support;                /* PCI-X */
323         u16 vendor_id;
324         struct work_struct int_task_event;
325         wait_queue_head_t queue;        /* sleep & wake process */
326 };
327
328 struct irq_mapping {
329         u8 barber_pole;
330         u8 valid_INT;
331         u8 interrupt[4];
332 };
333
334 struct resource_lists {
335         struct pci_resource *mem_head;
336         struct pci_resource *p_mem_head;
337         struct pci_resource *io_head;
338         struct pci_resource *bus_head;
339         struct irq_mapping *irqs;
340 };
341
342 #define ROM_PHY_ADDR                    0x0F0000
343 #define ROM_PHY_LEN                     0x00ffff
344
345 #define PCI_HPC_ID                      0xA0F7
346 #define PCI_SUB_HPC_ID                  0xA2F7
347 #define PCI_SUB_HPC_ID2                 0xA2F8
348 #define PCI_SUB_HPC_ID3                 0xA2F9
349 #define PCI_SUB_HPC_ID_INTC             0xA2FA
350 #define PCI_SUB_HPC_ID4                 0xA2FD
351
352 #define INT_BUTTON_IGNORE               0
353 #define INT_PRESENCE_ON                 1
354 #define INT_PRESENCE_OFF                2
355 #define INT_SWITCH_CLOSE                3
356 #define INT_SWITCH_OPEN                 4
357 #define INT_POWER_FAULT                 5
358 #define INT_POWER_FAULT_CLEAR           6
359 #define INT_BUTTON_PRESS                7
360 #define INT_BUTTON_RELEASE              8
361 #define INT_BUTTON_CANCEL               9
362
363 #define STATIC_STATE                    0
364 #define BLINKINGON_STATE                1
365 #define BLINKINGOFF_STATE               2
366 #define POWERON_STATE                   3
367 #define POWEROFF_STATE                  4
368
369 #define PCISLOT_INTERLOCK_CLOSED        0x00000001
370 #define PCISLOT_ADAPTER_PRESENT         0x00000002
371 #define PCISLOT_POWERED                 0x00000004
372 #define PCISLOT_66_MHZ_OPERATION        0x00000008
373 #define PCISLOT_64_BIT_OPERATION        0x00000010
374 #define PCISLOT_REPLACE_SUPPORTED       0x00000020
375 #define PCISLOT_ADD_SUPPORTED           0x00000040
376 #define PCISLOT_INTERLOCK_SUPPORTED     0x00000080
377 #define PCISLOT_66_MHZ_SUPPORTED        0x00000100
378 #define PCISLOT_64_BIT_SUPPORTED        0x00000200
379
380
381
382 #define PCI_TO_PCI_BRIDGE_CLASS         0x00060400
383
384
385 #define INTERLOCK_OPEN                  0x00000002
386 #define ADD_NOT_SUPPORTED               0x00000003
387 #define CARD_FUNCTIONING                0x00000005
388 #define ADAPTER_NOT_SAME                0x00000006
389 #define NO_ADAPTER_PRESENT              0x00000009
390 #define NOT_ENOUGH_RESOURCES            0x0000000B
391 #define DEVICE_TYPE_NOT_SUPPORTED       0x0000000C
392 #define POWER_FAILURE                   0x0000000E
393
394 #define REMOVE_NOT_SUPPORTED            0x00000003
395
396
397 /*
398  * error Messages
399  */
400 #define msg_initialization_err  "Initialization failure, error=%d\n"
401 #define msg_HPC_rev_error       "Unsupported revision of the PCI hot plug controller found.\n"
402 #define msg_HPC_non_compaq_or_intel     "The PCI hot plug controller is not supported by this driver.\n"
403 #define msg_HPC_not_supported   "this system is not supported by this version of cpqphpd. Upgrade to a newer version of cpqphpd\n"
404 #define msg_unable_to_save      "unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
405 #define msg_button_on           "PCI slot #%d - powering on due to button press.\n"
406 #define msg_button_off          "PCI slot #%d - powering off due to button press.\n"
407 #define msg_button_cancel       "PCI slot #%d - action canceled due to button press.\n"
408 #define msg_button_ignore       "PCI slot #%d - button press ignored.  (action in progress...)\n"
409
410
411 /* sysfs functions for the hotplug controller info */
412 extern void cpqhp_create_ctrl_files             (struct controller *ctrl);
413
414 /* controller functions */
415 extern void     cpqhp_pushbutton_thread         (unsigned long event_pointer);
416 extern irqreturn_t cpqhp_ctrl_intr              (int IRQ, void *data, struct pt_regs *regs);
417 extern int      cpqhp_find_available_resources  (struct controller *ctrl, void *rom_start);
418 extern int      cpqhp_event_start_thread        (void);
419 extern void     cpqhp_event_stop_thread         (void);
420 extern struct pci_func *cpqhp_slot_create       (unsigned char busnumber);
421 extern struct pci_func *cpqhp_slot_find         (unsigned char bus, unsigned char device, unsigned char index);
422 extern int      cpqhp_process_SI                (struct controller *ctrl, struct pci_func *func);
423 extern int      cpqhp_process_SS                (struct controller *ctrl, struct pci_func *func);
424 extern int      cpqhp_hardware_test             (struct controller *ctrl, int test_num);
425
426 /* resource functions */
427 extern int      cpqhp_resource_sort_and_combine (struct pci_resource **head);
428
429 /* pci functions */
430 extern int      cpqhp_set_irq                   (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
431 extern int      cpqhp_get_bus_dev               (struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot);
432 extern int      cpqhp_save_config               (struct controller *ctrl, int busnumber, int is_hot_plug);
433 extern int      cpqhp_save_base_addr_length     (struct controller *ctrl, struct pci_func * func);
434 extern int      cpqhp_save_used_resources       (struct controller *ctrl, struct pci_func * func);
435 extern int      cpqhp_configure_board           (struct controller *ctrl, struct pci_func * func);
436 extern int      cpqhp_save_slot_config          (struct controller *ctrl, struct pci_func * new_slot);
437 extern int      cpqhp_valid_replace             (struct controller *ctrl, struct pci_func * func);
438 extern void     cpqhp_destroy_board_resources   (struct pci_func * func);
439 extern int      cpqhp_return_board_resources    (struct pci_func * func, struct resource_lists * resources);
440 extern void     cpqhp_destroy_resource_list     (struct resource_lists * resources);
441 extern int      cpqhp_configure_device          (struct controller* ctrl, struct pci_func* func);
442 extern int      cpqhp_unconfigure_device        (struct pci_func* func);
443 extern struct slot *cpqhp_find_slot             (struct controller *ctrl, u8 device);
444
445 /* Global variables */
446 extern int cpqhp_debug;
447 extern int cpqhp_legacy_mode;
448 extern struct controller *cpqhp_ctrl_list;
449 extern struct pci_func *cpqhp_slot_list[256];
450
451 /* these can be gotten rid of, but for debugging they are purty */
452 extern u8 cpqhp_nic_irq;
453 extern u8 cpqhp_disk_irq;
454
455
456
457 /* inline functions */
458
459
460 /* Inline functions to check the sanity of a pointer that is passed to us */
461 static inline int slot_paranoia_check (struct slot *slot, const char *function)
462 {
463         if (!slot) {
464                 dbg("%s - slot == NULL", function);
465                 return -1;
466         }
467         if (slot->magic != SLOT_MAGIC) {
468                 dbg("%s - bad magic number for slot", function);
469                 return -1;
470         }
471         if (!slot->hotplug_slot) {
472                 dbg("%s - slot->hotplug_slot == NULL!", function);
473                 return -1;
474         }
475         return 0;
476 }
477
478 static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)
479
480         struct slot *slot;
481
482         if (!hotplug_slot) {
483                 dbg("%s - hotplug_slot == NULL\n", function);
484                 return NULL;
485         }
486
487         slot = (struct slot *)hotplug_slot->private;
488         if (slot_paranoia_check (slot, function))
489                 return NULL;
490         return slot;
491 }               
492
493 /*
494  * return_resource
495  *
496  * Puts node back in the resource list pointed to by head
497  *
498  */
499 static inline void return_resource (struct pci_resource **head, struct pci_resource *node)
500 {
501         if (!node || !head)
502                 return;
503         node->next = *head;
504         *head = node;
505 }
506
507 static inline void set_SOGO (struct controller *ctrl)
508 {
509         u16 misc;
510         
511         misc = readw(ctrl->hpc_reg + MISC);
512         misc = (misc | 0x0001) & 0xFFFB;
513         writew(misc, ctrl->hpc_reg + MISC);
514 }
515
516
517 static inline void amber_LED_on (struct controller *ctrl, u8 slot)
518 {
519         u32 led_control;
520         
521         led_control = readl(ctrl->hpc_reg + LED_CONTROL);
522         led_control |= (0x01010000L << slot);
523         writel(led_control, ctrl->hpc_reg + LED_CONTROL);
524 }
525
526
527 static inline void amber_LED_off (struct controller *ctrl, u8 slot)
528 {
529         u32 led_control;
530         
531         led_control = readl(ctrl->hpc_reg + LED_CONTROL);
532         led_control &= ~(0x01010000L << slot);
533         writel(led_control, ctrl->hpc_reg + LED_CONTROL);
534 }
535
536
537 static inline int read_amber_LED (struct controller *ctrl, u8 slot)
538 {
539         u32 led_control;
540
541         led_control = readl(ctrl->hpc_reg + LED_CONTROL);
542         led_control &= (0x01010000L << slot);
543         
544         return led_control ? 1 : 0;
545 }
546
547
548 static inline void green_LED_on (struct controller *ctrl, u8 slot)
549 {
550         u32 led_control;
551         
552         led_control = readl(ctrl->hpc_reg + LED_CONTROL);
553         led_control |= 0x0101L << slot;
554         writel(led_control, ctrl->hpc_reg + LED_CONTROL);
555 }
556
557 static inline void green_LED_off (struct controller *ctrl, u8 slot)
558 {
559         u32 led_control;
560         
561         led_control = readl(ctrl->hpc_reg + LED_CONTROL);
562         led_control &= ~(0x0101L << slot);
563         writel(led_control, ctrl->hpc_reg + LED_CONTROL);
564 }
565
566
567 static inline void green_LED_blink (struct controller *ctrl, u8 slot)
568 {
569         u32 led_control;
570         
571         led_control = readl(ctrl->hpc_reg + LED_CONTROL);
572         led_control &= ~(0x0101L << slot);
573         led_control |= (0x0001L << slot);
574         writel(led_control, ctrl->hpc_reg + LED_CONTROL);
575 }
576
577
578 static inline void slot_disable (struct controller *ctrl, u8 slot)
579 {
580         u8 slot_enable;
581
582         slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
583         slot_enable &= ~(0x01 << slot);
584         writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
585 }
586
587
588 static inline void slot_enable (struct controller *ctrl, u8 slot)
589 {
590         u8 slot_enable;
591
592         slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
593         slot_enable |= (0x01 << slot);
594         writeb(slot_enable, ctrl->hpc_reg + SLOT_ENABLE);
595 }
596
597
598 static inline u8 is_slot_enabled (struct controller *ctrl, u8 slot)
599 {
600         u8 slot_enable;
601
602         slot_enable = readb(ctrl->hpc_reg + SLOT_ENABLE);
603         slot_enable &= (0x01 << slot);
604         return slot_enable ? 1 : 0;
605 }
606
607
608 static inline u8 read_slot_enable (struct controller *ctrl)
609 {
610         return readb(ctrl->hpc_reg + SLOT_ENABLE);
611 }
612
613
614 /*
615  * get_controller_speed - find the current frequency/mode of controller.
616  *
617  * @ctrl: controller to get frequency/mode for.
618  *
619  * Returns controller speed.
620  *
621  */
622 static inline u8 get_controller_speed (struct controller *ctrl)
623 {
624         u8 curr_freq;
625         u16 misc;
626         
627         if (ctrl->pcix_support) {
628                 curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
629                 if ((curr_freq & 0xB0) == 0xB0) 
630                         return PCI_SPEED_133MHz_PCIX;
631                 if ((curr_freq & 0xA0) == 0xA0)
632                         return PCI_SPEED_100MHz_PCIX;
633                 if ((curr_freq & 0x90) == 0x90)
634                         return PCI_SPEED_66MHz_PCIX;
635                 if (curr_freq & 0x10)
636                         return PCI_SPEED_66MHz;
637
638                 return PCI_SPEED_33MHz;
639         }
640
641         misc = readw(ctrl->hpc_reg + MISC);
642         return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
643 }
644  
645
646 /*
647  * get_adapter_speed - find the max supported frequency/mode of adapter.
648  *
649  * @ctrl: hotplug controller.
650  * @hp_slot: hotplug slot where adapter is installed.
651  *
652  * Returns adapter speed.
653  *
654  */
655 static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot)
656 {
657         u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT);
658         dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword);
659         if (ctrl->pcix_support) {
660                 if (temp_dword & (0x10000 << hp_slot))
661                         return PCI_SPEED_133MHz_PCIX;
662                 if (temp_dword & (0x100 << hp_slot))
663                         return PCI_SPEED_66MHz_PCIX;
664         }
665
666         if (temp_dword & (0x01 << hp_slot))
667                 return PCI_SPEED_66MHz;
668
669         return PCI_SPEED_33MHz;
670 }
671
672 static inline void enable_slot_power (struct controller *ctrl, u8 slot)
673 {
674         u8 slot_power;
675
676         slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
677         slot_power |= (0x01 << slot);
678         writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
679 }
680
681 static inline void disable_slot_power (struct controller *ctrl, u8 slot)
682 {
683         u8 slot_power;
684
685         slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
686         slot_power &= ~(0x01 << slot);
687         writeb(slot_power, ctrl->hpc_reg + SLOT_POWER);
688 }
689
690
691 static inline int cpq_get_attention_status (struct controller *ctrl, struct slot *slot)
692 {
693         u8 hp_slot;
694
695         if (slot == NULL)
696                 return 1;
697
698         hp_slot = slot->device - ctrl->slot_device_offset;
699
700         return read_amber_LED (ctrl, hp_slot);
701 }
702
703
704 static inline int get_slot_enabled (struct controller *ctrl, struct slot *slot)
705 {
706         u8 hp_slot;
707
708         if (slot == NULL)
709                 return 1;
710
711         hp_slot = slot->device - ctrl->slot_device_offset;
712
713         return is_slot_enabled (ctrl, hp_slot);
714 }
715
716
717 static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *slot)
718 {
719         u32 status;
720         u8 hp_slot;
721
722         if (slot == NULL)
723                 return 1;
724
725         hp_slot = slot->device - ctrl->slot_device_offset;
726         dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n",
727             __FUNCTION__, slot->device, ctrl->slot_device_offset);
728
729         status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot));
730
731         return(status == 0) ? 1 : 0;
732 }
733
734
735 static inline int get_presence_status (struct controller *ctrl, struct slot *slot)
736 {
737         int presence_save = 0;
738         u8 hp_slot;
739         u32 tempdword;
740
741         if (slot == NULL)
742                 return 0;
743
744         hp_slot = slot->device - ctrl->slot_device_offset;
745
746         tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
747         presence_save = (int) ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> hp_slot) & 0x02;
748
749         return presence_save;
750 }
751
752 #define SLOT_NAME_SIZE 10
753
754 static inline void make_slot_name (char *buffer, int buffer_size, struct slot *slot)
755 {
756         snprintf (buffer, buffer_size, "%d", slot->number);
757 }
758
759
760 static inline int wait_for_ctrl_irq (struct controller *ctrl)
761 {
762         DECLARE_WAITQUEUE(wait, current);
763         int retval = 0;
764
765         dbg("%s - start\n", __FUNCTION__);
766         add_wait_queue(&ctrl->queue, &wait);
767         set_current_state(TASK_INTERRUPTIBLE);
768         /* Sleep for up to 1 second to wait for the LED to change. */
769         schedule_timeout(1*HZ);
770         remove_wait_queue(&ctrl->queue, &wait);
771         if (signal_pending(current))
772                 retval =  -EINTR;
773
774         dbg("%s - end\n", __FUNCTION__);
775         return retval;
776 }
777
778
779 /**
780  * set_controller_speed - set the frequency and/or mode of a specific
781  * controller segment.
782  *
783  * @ctrl: controller to change frequency/mode for.
784  * @adapter_speed: the speed of the adapter we want to match.
785  * @hp_slot: the slot number where the adapter is installed.
786  *
787  * Returns 0 if we successfully change frequency and/or mode to match the
788  * adapter speed.
789  * 
790  */
791 static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
792 {
793         struct slot *slot;
794         u8 reg;
795         u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
796         u16 reg16;
797         u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
798         
799         if (ctrl->speed == adapter_speed)
800                 return 0;
801         
802         /* We don't allow freq/mode changes if we find another adapter running
803          * in another slot on this controller */
804         for(slot = ctrl->slot; slot; slot = slot->next) {
805                 if (slot->device == (hp_slot + ctrl->slot_device_offset)) 
806                         continue;
807                 if (!slot->hotplug_slot && !slot->hotplug_slot->info) 
808                         continue;
809                 if (slot->hotplug_slot->info->adapter_status == 0) 
810                         continue;
811                 /* If another adapter is running on the same segment but at a
812                  * lower speed/mode, we allow the new adapter to function at
813                  * this rate if supported */
814                 if (ctrl->speed < adapter_speed) 
815                         return 0;
816
817                 return 1;
818         }
819         
820         /* If the controller doesn't support freq/mode changes and the
821          * controller is running at a higher mode, we bail */
822         if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
823                 return 1;
824         
825         /* But we allow the adapter to run at a lower rate if possible */
826         if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
827                 return 0;
828
829         /* We try to set the max speed supported by both the adapter and
830          * controller */
831         if (ctrl->speed_capability < adapter_speed) {
832                 if (ctrl->speed == ctrl->speed_capability)
833                         return 0;
834                 adapter_speed = ctrl->speed_capability;
835         }
836
837         writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
838         writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
839         
840         set_SOGO(ctrl); 
841         wait_for_ctrl_irq(ctrl);
842         
843         if (adapter_speed != PCI_SPEED_133MHz_PCIX)
844                 reg = 0xF5;
845         else
846                 reg = 0xF4;     
847         pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
848         
849         reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
850         reg16 &= ~0x000F;
851         switch(adapter_speed) {
852                 case(PCI_SPEED_133MHz_PCIX): 
853                         reg = 0x75;
854                         reg16 |= 0xB; 
855                         break;
856                 case(PCI_SPEED_100MHz_PCIX):
857                         reg = 0x74;
858                         reg16 |= 0xA;
859                         break;
860                 case(PCI_SPEED_66MHz_PCIX):
861                         reg = 0x73;
862                         reg16 |= 0x9;
863                         break;
864                 case(PCI_SPEED_66MHz):
865                         reg = 0x73;
866                         reg16 |= 0x1;
867                         break;
868                 default: /* 33MHz PCI 2.2 */
869                         reg = 0x71;
870                         break;
871                         
872         }
873         reg16 |= 0xB << 12;
874         writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
875         
876         mdelay(5); 
877         
878         /* Reenable interrupts */
879         writel(0, ctrl->hpc_reg + INT_MASK);
880
881         pci_write_config_byte(ctrl->pci_dev, 0x41, reg); 
882         
883         /* Restart state machine */
884         reg = ~0xF;
885         pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
886         pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
887         
888         /* Only if mode change...*/
889         if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
890                 ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
891                         set_SOGO(ctrl);
892         
893         wait_for_ctrl_irq(ctrl);
894         mdelay(1100);
895         
896         /* Restore LED/Slot state */
897         writel(leds, ctrl->hpc_reg + LED_CONTROL);
898         writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
899         
900         set_SOGO(ctrl);
901         wait_for_ctrl_irq(ctrl);
902
903         ctrl->speed = adapter_speed;
904         slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
905
906         info("Successfully changed frequency/mode for adapter in slot %d\n", 
907                         slot->number);
908         return 0;
909 }
910
911 #endif
912