added mtd driver
[linux-2.4.git] / drivers / hotplug / pciehp_hpc.c
1 /*
2  * PCI Express PCI Hot Plug 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 Corp.
7  * Copyright (C) 2003-2004 Intel Corporation
8  *
9  * All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19  * NON INFRINGEMENT.  See the GNU General Public License for more
20  * details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com>
27  *
28  */
29
30 #include <linux/config.h>
31 #include <linux/kernel.h>
32 #include <linux/module.h>
33 #include <linux/types.h>
34 #include <linux/slab.h>
35 #include <linux/vmalloc.h>
36 #include <linux/interrupt.h>
37 #include <linux/spinlock.h>
38 #include <linux/pci.h>
39 #include <asm/system.h>
40 #include "pciehp.h"
41
42 #ifdef DEBUG
43 #define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)       /* On function entry */
44 #define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)       /* On function exit */
45 #define DBG_K_INFO             ((unsigned int)0x00000004)       /* Info messages */
46 #define DBG_K_ERROR            ((unsigned int)0x00000008)       /* Error messages */
47 #define DBG_K_TRACE            (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT)
48 #define DBG_K_STANDARD         (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE)
49 /* Redefine this flagword to set debug level */
50 #define DEBUG_LEVEL            DBG_K_STANDARD
51
52 #define DEFINE_DBG_BUFFER     char __dbg_str_buf[256];
53
54 #define DBG_PRINT( dbg_flags, args... )                  \
55         do {                                             \
56           if ( DEBUG_LEVEL & ( dbg_flags ) )             \
57           {                                              \
58             int len;                                     \
59             len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \
60                   __FILE__, __LINE__, __FUNCTION__ );    \
61             sprintf( __dbg_str_buf + len, args );        \
62             printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \
63           }                                              \
64         } while (0)
65
66 #define DBG_ENTER_ROUTINE       DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]");
67 #define DBG_LEAVE_ROUTINE       DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]");
68 #else
69 #define DEFINE_DBG_BUFFER
70 #define DBG_ENTER_ROUTINE
71 #define DBG_LEAVE_ROUTINE
72 #endif                          /* DEBUG */
73
74 struct ctrl_reg {
75         u8 cap_id;
76         u8 nxt_ptr;
77         u16 cap_reg;
78         u32 dev_cap;
79         u16 dev_ctrl;
80         u16 dev_status;
81         u32 lnk_cap;
82         u16 lnk_ctrl;
83         u16 lnk_status;
84         u32 slot_cap;
85         u16 slot_ctrl;
86         u16 slot_status;
87         u16 root_ctrl;
88         u16 rsvp;
89         u32 root_status;
90 } __attribute__ ((packed));
91
92 /* offsets to the controller registers based on the above structure layout */
93 enum ctrl_offsets {
94         PCIECAPID       =       offsetof(struct ctrl_reg, cap_id),
95         NXTCAPPTR       =       offsetof(struct ctrl_reg, nxt_ptr),
96         CAPREG          =       offsetof(struct ctrl_reg, cap_reg),
97         DEVCAP          =       offsetof(struct ctrl_reg, dev_cap),
98         DEVCTRL         =       offsetof(struct ctrl_reg, dev_ctrl),
99         DEVSTATUS       =       offsetof(struct ctrl_reg, dev_status),
100         LNKCAP          =       offsetof(struct ctrl_reg, lnk_cap),
101         LNKCTRL         =       offsetof(struct ctrl_reg, lnk_ctrl),
102         LNKSTATUS       =       offsetof(struct ctrl_reg, lnk_status),
103         SLOTCAP         =       offsetof(struct ctrl_reg, slot_cap),
104         SLOTCTRL        =       offsetof(struct ctrl_reg, slot_ctrl),
105         SLOTSTATUS      =       offsetof(struct ctrl_reg, slot_status),
106         ROOTCTRL        =       offsetof(struct ctrl_reg, root_ctrl),
107         ROOTSTATUS      =       offsetof(struct ctrl_reg, root_status),
108 };
109 static int pcie_cap_base = 0;   /* Base of the PCI Express capability item structure */
110
111 #define PCIE_CAP_ID     ( pcie_cap_base + PCIECAPID )
112 #define NXT_CAP_PTR     ( pcie_cap_base + NXTCAPPTR )
113 #define CAP_REG         ( pcie_cap_base + CAPREG )
114 #define DEV_CAP         ( pcie_cap_base + DEVCAP )
115 #define DEV_CTRL        ( pcie_cap_base + DEVCTRL )
116 #define DEV_STATUS      ( pcie_cap_base + DEVSTATUS )
117 #define LNK_CAP         ( pcie_cap_base + LNKCAP )
118 #define LNK_CTRL        ( pcie_cap_base + LNKCTRL )
119 #define LNK_STATUS      ( pcie_cap_base + LNKSTATUS )
120 #define SLOT_CAP        ( pcie_cap_base + SLOTCAP )
121 #define SLOT_CTRL       ( pcie_cap_base + SLOTCTRL )
122 #define SLOT_STATUS     ( pcie_cap_base + SLOTSTATUS )
123 #define ROOT_CTRL       ( pcie_cap_base + ROOTCTRL )
124 #define ROOT_STATUS     ( pcie_cap_base + ROOTSTATUS )
125
126 #define hp_register_read_word(pdev, reg , value)                \
127         pci_read_config_word(pdev, reg, &value)
128
129 #define hp_register_read_dword(pdev, reg , value)               \
130         pci_read_config_dword(pdev, reg, &value)
131  
132 #define hp_register_write_word(pdev, reg , value)               \
133         pci_write_config_word(pdev, reg, value)
134
135 #define hp_register_dwrite_word(pdev, reg , value)              \
136         pci_write_config_dword(pdev, reg, value)
137
138 /* Field definitions in PCI Express Capabilities Register */
139 #define CAP_VER         0x000F
140 #define DEV_PORT_TYPE   0x00F0
141 #define SLOT_IMPL       0x0100
142 #define MSG_NUM         0x3E00
143
144 /* Device or Port Type */
145 #define NAT_ENDPT       0x00
146 #define LEG_ENDPT       0x01
147 #define ROOT_PORT       0x04
148 #define UP_STREAM       0x05
149 #define DN_STREAM       0x06
150 #define PCIE_PCI_BRDG   0x07
151 #define PCI_PCIE_BRDG   0x10
152
153 /* Field definitions in Device Capabilities Register */
154 #define DATTN_BUTTN_PRSN        0x1000
155 #define DATTN_LED_PRSN  0x2000
156 #define DPWR_LED_PRSN   0x4000
157
158 /* Field definitions in Link Capabilities Register */
159 #define MAX_LNK_SPEED   0x000F
160 #define MAX_LNK_WIDTH   0x03F0
161
162 /* Link Width Encoding */
163 #define LNK_X1          0x01
164 #define LNK_X2          0x02
165 #define LNK_X4          0x04    
166 #define LNK_X8          0x08
167 #define LNK_X12         0x0C
168 #define LNK_X16         0x10    
169 #define LNK_X32         0x20
170
171 /*Field definitions of Link Status Register */
172 #define LNK_SPEED       0x000F
173 #define NEG_LINK_WD     0x03F0
174 #define LNK_TRN_ERR     0x0400
175 #define LNK_TRN         0x0800
176 #define SLOT_CLK_CONF   0x1000
177
178 /* Field definitions in Slot Capabilities Register */
179 #define ATTN_BUTTN_PRSN 0x00000001
180 #define PWR_CTRL_PRSN   0x00000002
181 #define MRL_SENS_PRSN   0x00000004
182 #define ATTN_LED_PRSN   0x00000008
183 #define PWR_LED_PRSN    0x00000010
184 #define HP_SUPR_RM      0x00000020
185 #define HP_CAP          0x00000040
186 #define SLOT_PWR_VALUE  0x000003F8
187 #define SLOT_PWR_LIMIT  0x00000C00
188 #define PSN             0xFFF80000      /* PSN: Physical Slot Number */
189
190 /* Field definitions in Slot Control Register */
191 #define ATTN_BUTTN_ENABLE               0x0001
192 #define PWR_FAULT_DETECT_ENABLE         0x0002
193 #define MRL_DETECT_ENABLE               0x0004
194 #define PRSN_DETECT_ENABLE              0x0008
195 #define CMD_CMPL_INTR_ENABLE            0x0010
196 #define HP_INTR_ENABLE                  0x0020
197 #define ATTN_LED_CTRL                   0x00C0
198 #define PWR_LED_CTRL                    0x0300
199 #define PWR_CTRL                        0x0400
200
201 /* Attention indicator and Power indicator states */
202 #define LED_ON          0x01
203 #define LED_BLINK       0x10
204 #define LED_OFF         0x11
205
206 /* Power Control Command */
207 #define POWER_ON        0
208 #define POWER_OFF       0x0400  
209
210 /* Field definitions in Slot Status Register */
211 #define ATTN_BUTTN_PRESSED      0x0001
212 #define PWR_FAULT_DETECTED      0x0002
213 #define MRL_SENS_CHANGED        0x0004
214 #define PRSN_DETECT_CHANGED     0x0008
215 #define CMD_COMPLETED           0x0010
216 #define MRL_STATE               0x0020
217 #define PRSN_STATE              0x0040
218
219 struct php_ctlr_state_s {
220         struct php_ctlr_state_s *pnext;
221         struct pci_dev *pci_dev;
222         unsigned int irq;
223         unsigned long flags;                            /* spinlock's */
224         u32 slot_device_offset;
225         u32 num_slots;
226         struct timer_list       int_poll_timer; /* Added for poll event */
227         php_intr_callback_t attention_button_callback;
228         php_intr_callback_t switch_change_callback;
229         php_intr_callback_t presence_change_callback;
230         php_intr_callback_t power_fault_callback;
231         void *callback_instance_id;
232         struct ctrl_reg *creg;                          /* Ptr to controller register space */
233 };
234
235 static spinlock_t hpc_event_lock;
236
237 DEFINE_DBG_BUFFER               /* Debug string buffer for entire HPC defined here */
238 static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */
239 static int ctlr_seq_num = 0;    /* Controller sequence # */
240 static spinlock_t list_lock;
241 static void pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
242
243 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
244
245 /* This is the interrupt polling timeout function. */
246 static void int_poll_timeout(unsigned long lphp_ctlr)
247 {
248     struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr;
249
250     DBG_ENTER_ROUTINE
251
252     if ( !php_ctlr ) {
253                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
254                 return;
255     }
256
257     /* Poll for interrupt events.  regs == NULL => polling */
258     pcie_isr( 0, (void *)php_ctlr, NULL );
259
260     init_timer(&php_ctlr->int_poll_timer);
261
262         if (!pciehp_poll_time)
263                 pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/
264
265     start_int_poll_timer(php_ctlr, pciehp_poll_time);
266         
267         return;
268 }
269
270 /* This function starts the interrupt polling timer. */
271 static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
272 {
273         if (!php_ctlr) {
274                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
275                 return;
276         }
277
278         if ( ( seconds <= 0 ) || ( seconds > 60 ) )
279                 seconds = 2;            /* Clamp to sane value */
280
281         php_ctlr->int_poll_timer.function = &int_poll_timeout;
282         php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;    /* Instance data */
283         php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ;
284         add_timer(&php_ctlr->int_poll_timer);
285
286         return;
287 }
288
289 static int pcie_write_cmd(struct slot *slot, u16 cmd)
290 {
291         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
292         int retval = 0;
293         u16 slot_status;
294
295         DBG_ENTER_ROUTINE 
296         
297         dbg("%s : Enter\n", __FUNCTION__);
298         if (!slot->ctrl->hpc_ctlr_handle) {
299                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
300                 return -1;
301         }
302
303         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
304         if (retval) {
305                         err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
306                         return retval;
307                 }
308         dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status);
309         
310         if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { 
311                 /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue 
312                    the next command according to spec.  Just print out the error message */
313                 dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
314         }
315
316         dbg("%s : Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
317         retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | CMD_CMPL_INTR_ENABLE);
318         if (retval) {
319                 err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
320                 return retval;
321         }
322         dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd|CMD_CMPL_INTR_ENABLE);
323         dbg("%s : Exit\n", __FUNCTION__);
324
325         DBG_LEAVE_ROUTINE 
326         return retval;
327 }
328
329 static int hpc_check_lnk_status(struct controller *ctrl)
330 {
331         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
332         u16 lnk_status;
333         int retval = 0;
334
335         DBG_ENTER_ROUTINE 
336
337         if (!ctrl->hpc_ctlr_handle) {
338                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
339                 return -1;
340         }
341         
342         retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
343
344         if (retval) {
345                 err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
346                 return retval;
347         }
348
349         dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
350         if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) || 
351                 !(lnk_status & NEG_LINK_WD)) {
352                 err("%s : Link Training Error occurs \n", __FUNCTION__);
353                 return -1;
354         }
355
356         DBG_LEAVE_ROUTINE 
357         return retval;
358 }
359
360
361 static int hpc_get_attention_status(struct slot *slot, u8 *status)
362 {
363         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
364         u16 slot_ctrl;
365         u8 atten_led_state;
366         int retval = 0;
367         
368         DBG_ENTER_ROUTINE 
369
370         if (!slot->ctrl->hpc_ctlr_handle) {
371                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
372                 return -1;
373         }
374
375         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
376
377         if (retval) {
378                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
379                 return retval;
380         }
381
382         dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, slot_ctrl);
383
384         atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
385         //atten_led_state = (slot_ctrl & PWR_LED_CTRL) >> 8;
386
387         switch (atten_led_state) {
388         case 0:
389                 *status = 0xFF; /* Reserved */
390                 break;
391         case 1:
392                 *status = 1;    /* On */
393                 break;
394         case 2:
395                 *status = 2;    /* Blink */
396                 break;
397         case 3:
398                 *status = 0;    /* Off */
399                 break;
400         default:
401                 *status = 0xFF;
402                 break;
403         }
404
405         DBG_LEAVE_ROUTINE 
406         return 0;
407 }
408
409 static int hpc_get_power_status(struct slot * slot, u8 *status)
410 {
411         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
412         u16 slot_ctrl;
413         u8 pwr_state;
414         int     retval = 0;
415         
416         DBG_ENTER_ROUTINE 
417
418         if (!slot->ctrl->hpc_ctlr_handle) {
419                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
420                 return -1;
421         }
422
423         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
424
425         if (retval) {
426                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
427                 return retval;
428         }
429         dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
430
431         pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
432
433         switch (pwr_state) {
434         case 0:
435                 *status = 1; 
436                 break;
437         case 1:
438                 *status = 0;    
439                 break;
440         default:
441                 *status = 0xFF;
442                 break;
443         }
444
445         DBG_LEAVE_ROUTINE 
446         return retval;
447 }
448
449
450 static int hpc_get_latch_status(struct slot *slot, u8 *status)
451 {
452         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
453         u16 slot_status;
454         int retval = 0;
455
456         DBG_ENTER_ROUTINE 
457
458         if (!slot->ctrl->hpc_ctlr_handle) {
459                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
460                 return -1;
461         }
462
463         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
464
465         if (retval) {
466                 err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
467                 return retval;
468         }
469
470         *status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1;  
471
472         DBG_LEAVE_ROUTINE 
473         return 0;
474 }
475
476 static int hpc_get_adapter_status(struct slot *slot, u8 *status)
477 {
478         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
479         u16 slot_status;
480         u8 card_state;
481         int retval = 0;
482
483         DBG_ENTER_ROUTINE 
484
485         if (!slot->ctrl->hpc_ctlr_handle) {
486                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
487                 return -1;
488         }
489
490         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
491
492         if (retval) {
493                 err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
494                 return retval;
495         }
496         card_state = (u8)((slot_status & PRSN_STATE) >> 6);
497         *status = (card_state == 1) ? 1 : 0;
498
499         DBG_LEAVE_ROUTINE 
500         return 0;
501 }
502
503
504 static int hpc_query_power_fault(struct slot * slot)
505 {
506         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
507         u16 slot_status;
508         u8 pwr_fault;
509         int retval = 0;
510         u8 status;
511
512         DBG_ENTER_ROUTINE 
513
514         if (!slot->ctrl->hpc_ctlr_handle) {
515                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
516                 return -1;
517         }
518
519         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
520
521         if (retval) {
522                 err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
523                 return retval;
524         }
525         pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
526         status = (pwr_fault != 1) ? 1 : 0;
527         
528         DBG_LEAVE_ROUTINE
529         /* Note: Logic 0 => fault */
530         return status;
531 }
532
533 static int hpc_set_attention_status(struct slot *slot, u8 value)
534 {
535         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
536         u16 slot_cmd = 0;
537         u16 slot_ctrl;
538         int rc = 0;
539
540         dbg("%s: \n", __FUNCTION__);    
541         if (!slot->ctrl->hpc_ctlr_handle) {
542                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
543                 return -1;
544         }
545
546         if (slot->hp_slot >= php_ctlr->num_slots) {
547                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
548                 return -1;
549         }
550         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
551
552         if (rc) {
553                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
554                 return rc;
555         }
556         dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
557
558         switch (value) {
559                 case 0 :        /* turn off */
560                         slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0;
561                         //slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
562                         break;
563                 case 1:         /* turn on */
564                         slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
565                         //slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
566                         break;
567                 case 2:         /* turn blink */
568                         slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
569                         //slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; 
570                         break;
571                 default:
572                         return -1;
573         }
574         if (!pciehp_poll_mode)
575                 slot_cmd = slot_cmd | HP_INTR_ENABLE; 
576
577         pcie_write_cmd(slot, slot_cmd);
578         dbg("%s: SLOT_CTRL %x write cmd %x\n", 
579                 __FUNCTION__, SLOT_CTRL, slot_cmd);
580         
581         return rc;
582 }
583
584
585 static void hpc_set_green_led_on(struct slot *slot)
586 {
587         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
588         u16 slot_cmd;
589         u16 slot_ctrl;
590         int rc = 0;
591        
592         dbg("%s: \n", __FUNCTION__);    
593         if (!slot->ctrl->hpc_ctlr_handle) {
594                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
595                 return ;
596         }
597
598         if (slot->hp_slot >= php_ctlr->num_slots) {
599                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
600                 return ;
601         }
602
603         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
604
605         if (rc) {
606                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
607                 return ;
608         }
609         dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
610         slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
611         //slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
612
613         if (!pciehp_poll_mode)
614                 slot_cmd = slot_cmd | HP_INTR_ENABLE; 
615  
616         pcie_write_cmd(slot, slot_cmd);
617
618         dbg("%s: SLOT_CTRL %x write cmd %x\n", 
619                 __FUNCTION__, SLOT_CTRL, slot_cmd);
620         return;
621 }
622
623 static void hpc_set_green_led_off(struct slot *slot)
624 {
625         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
626         u16 slot_cmd;
627         u16 slot_ctrl;
628         int rc = 0;
629
630         dbg("%s: \n", __FUNCTION__);    
631         if (!slot->ctrl->hpc_ctlr_handle) {
632                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
633                 return ;
634         }
635
636         if (slot->hp_slot >= php_ctlr->num_slots) {
637                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
638                 return ;
639         }
640
641         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
642
643         if (rc) {
644                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
645                 return;
646         }
647         dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
648
649         slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
650         //slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00c0;
651
652         if (!pciehp_poll_mode)
653                 slot_cmd = slot_cmd | HP_INTR_ENABLE; 
654         pcie_write_cmd(slot, slot_cmd);
655
656         dbg("%s: SLOT_CTRL %x write cmd %x\n", 
657                 __FUNCTION__, SLOT_CTRL, slot_cmd);
658         return;
659 }
660
661 static void hpc_set_green_led_blink(struct slot *slot)
662 {
663         struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
664         u16 slot_cmd;
665         u16 slot_ctrl;
666         int rc = 0; 
667         
668         dbg("%s: \n", __FUNCTION__);    
669         if (!slot->ctrl->hpc_ctlr_handle) {
670                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
671                 return ;
672         }
673
674         if (slot->hp_slot >= php_ctlr->num_slots) {
675                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
676                 return ;
677         }
678
679         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
680
681         if (rc) {
682                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
683                 return;
684         }
685         dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
686
687         slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
688         //slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
689
690         if (!pciehp_poll_mode)
691                 slot_cmd = slot_cmd | HP_INTR_ENABLE; 
692         pcie_write_cmd(slot, slot_cmd);
693
694         dbg("%s: SLOT_CTRL %x write cmd %x\n", 
695                 __FUNCTION__, SLOT_CTRL, slot_cmd);
696         return;
697 }
698
699 int pcie_get_ctlr_slot_config(struct controller *ctrl,
700         int *num_ctlr_slots,    /* number of slots in this HPC; only 1 in PCIE  */
701         int *first_device_num,  /* PCI dev num of the first slot in this PCIE   */
702         int *physical_slot_num, /* phy slot num of the first slot in this PCIE  */
703         int *updown,            /* physical_slot_num increament: 1 or -1 */
704         int *flags)
705 {
706         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
707         u32 slot_cap;
708         int rc = 0;
709         
710         DBG_ENTER_ROUTINE 
711
712         if (!ctrl->hpc_ctlr_handle) {
713                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
714                 return -1;
715         }
716
717         *first_device_num = 0;
718         *num_ctlr_slots = 1; 
719
720         rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
721         if (rc) {
722                 err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__);
723                 return -1;
724         }
725
726         *physical_slot_num = slot_cap >> 19;
727         *updown = -1;
728
729         DBG_LEAVE_ROUTINE 
730         return 0;
731 }
732
733 static void hpc_release_ctlr(struct controller *ctrl)
734 {
735         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle;
736         struct php_ctlr_state_s *p, *p_prev;
737
738         DBG_ENTER_ROUTINE 
739
740         if (!ctrl->hpc_ctlr_handle) {
741                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
742                 return ;
743         }
744
745         if (pciehp_poll_mode) {
746             del_timer(&php_ctlr->int_poll_timer);
747         } else {        
748                 if (php_ctlr->irq) {
749                         free_irq(php_ctlr->irq, ctrl);
750                         php_ctlr->irq = 0;
751                 }
752         }
753         if (php_ctlr->pci_dev)
754                 php_ctlr->pci_dev = 0;
755
756         spin_lock(&list_lock);  
757         p = php_ctlr_list_head;
758         p_prev = NULL;
759         while (p) {
760                 if (p == php_ctlr) {
761                         if (p_prev)
762                                 p_prev->pnext = p->pnext;
763                         else
764                                 php_ctlr_list_head = p->pnext;
765                         break;
766                 } else {
767                         p_prev = p;
768                         p = p->pnext;
769                 }
770         }
771         spin_unlock(&list_lock);
772
773         kfree(php_ctlr);
774
775         DBG_LEAVE_ROUTINE
776                           
777 }
778
779 static int hpc_power_on_slot(struct slot * slot)
780 {
781         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
782         u16 slot_cmd;
783         u16 slot_ctrl;
784
785         int retval = 0;
786
787         DBG_ENTER_ROUTINE 
788         dbg("%s: \n", __FUNCTION__);    
789
790         if (!slot->ctrl->hpc_ctlr_handle) {
791                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
792                 return -1;
793         }
794         dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
795         if (slot->hp_slot >= php_ctlr->num_slots) {
796                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
797                 return -1;
798         }
799
800         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
801
802         if (retval) {
803                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
804                 return retval;
805         }
806         dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL, 
807                 slot_ctrl);
808
809         slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
810
811         if (!pciehp_poll_mode)
812                 slot_cmd = slot_cmd | HP_INTR_ENABLE; 
813
814         retval = pcie_write_cmd(slot, slot_cmd);
815
816         if (retval) {
817                 err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
818                 return -1;
819         }
820         dbg("%s: SLOT_CTRL %x write cmd %x\n", 
821                 __FUNCTION__, SLOT_CTRL, slot_cmd);
822
823         DBG_LEAVE_ROUTINE
824
825         return retval;
826 }
827
828 static int hpc_power_off_slot(struct slot * slot)
829 {
830         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
831         u16 slot_cmd;
832         u16 slot_ctrl;
833
834         int retval = 0;
835
836         DBG_ENTER_ROUTINE 
837         dbg("%s: \n", __FUNCTION__);    
838
839         if (!slot->ctrl->hpc_ctlr_handle) {
840                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
841                 return -1;
842         }
843         
844         dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
845         slot->hp_slot = 0;
846         if (slot->hp_slot >= php_ctlr->num_slots) {
847                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
848                 return -1;
849         }
850         retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
851
852         if (retval) {
853                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
854                 return retval;
855         }
856         dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL, 
857                 slot_ctrl);
858
859         slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
860
861         if (!pciehp_poll_mode)
862                 slot_cmd = slot_cmd | HP_INTR_ENABLE; 
863         
864         retval = pcie_write_cmd(slot, slot_cmd);
865
866         if (retval) {
867                 err("%s: Write command failed!\n", __FUNCTION__);
868                 return -1;
869         }
870         dbg("%s: SLOT_CTRL %x write cmd %x\n", 
871                 __FUNCTION__, SLOT_CTRL, slot_cmd);
872
873         DBG_LEAVE_ROUTINE
874
875         return retval;
876 }
877
878 static void pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
879 {
880         struct controller *ctrl = NULL; 
881         struct php_ctlr_state_s *php_ctlr;
882         u8 schedule_flag = 0;
883         u16 slot_status, intr_detect, intr_loc;
884         u16 temp_word;
885         int hp_slot = 0;        /* only 1 slot per PCI Express port */
886         int rc = 0;
887
888         if (!dev_id) {
889                 dbg("%s: dev_id == NULL\n", __FUNCTION__);
890                 return;
891         }
892
893         if (!pciehp_poll_mode) { 
894                 ctrl = (struct controller *)dev_id;
895                 php_ctlr = ctrl->hpc_ctlr_handle;
896         } else { 
897                 php_ctlr = (struct php_ctlr_state_s *) dev_id;
898                 ctrl = (struct controller *)php_ctlr->callback_instance_id;
899         }
900
901         if (!ctrl) {
902                 dbg("%s: dev_id %p ctlr == NULL\n", __FUNCTION__, (void*) dev_id);
903                 return;
904         }
905         if (!php_ctlr) {
906                 dbg("%s: php_ctlr == NULL\n", __FUNCTION__);
907                 return;
908         }
909         
910         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
911         if (rc) {
912                 err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
913                 return;
914         }
915
916         intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED |
917                                         PRSN_DETECT_CHANGED | CMD_COMPLETED );
918
919         intr_loc = slot_status & intr_detect;
920         
921         /* Check to see if it was our interrupt */
922         if ( !intr_loc ) 
923                 return;
924         
925         dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
926         
927         /* Mask Hot-plug Interrupt Enable */
928         if (!pciehp_poll_mode) {
929                 rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
930                 if (rc) {
931                         err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
932                         return;
933                 }
934
935                 temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
936
937                 rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
938                 if (rc) {
939                         err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
940                         return;
941                 }
942                 
943                 rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
944                 if (rc) {
945                         err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
946                         return;
947                 }
948                 
949                 /* Clear command complete interrupt caused by this write */
950                 temp_word = 0x1f;
951                 rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
952                 if (rc) {
953                         err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
954                         return;
955                 }
956         }
957
958         if (intr_loc & CMD_COMPLETED) {
959                 /* 
960                  * Command Complete Interrupt Pending 
961                  */
962                 dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__);
963                 wake_up_interruptible(&ctrl->queue);
964         }
965         if ((php_ctlr->switch_change_callback) && (intr_loc & MRL_SENS_CHANGED))
966                 schedule_flag += php_ctlr->switch_change_callback(
967                         hp_slot, php_ctlr->callback_instance_id);
968         if ((php_ctlr->attention_button_callback) && (intr_loc & ATTN_BUTTN_PRESSED))
969                 schedule_flag += php_ctlr->attention_button_callback(
970                         hp_slot, php_ctlr->callback_instance_id);
971         if ((php_ctlr->presence_change_callback) && (intr_loc & PRSN_DETECT_CHANGED))
972                 schedule_flag += php_ctlr->presence_change_callback(
973                         hp_slot , php_ctlr->callback_instance_id);
974         if ((php_ctlr->power_fault_callback) && (intr_loc & PWR_FAULT_DETECTED))
975                 schedule_flag += php_ctlr->power_fault_callback(
976                         hp_slot, php_ctlr->callback_instance_id);
977
978         /* Clear all events after serving them */
979         temp_word = 0x1F;
980         rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
981         if (rc) {
982                 err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
983                 return;
984         }
985
986         /* Unmask Hot-plug Interrupt Enable */
987         if (!pciehp_poll_mode) {
988                 rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
989                 if (rc) {
990                         err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
991                         return;
992                 }
993                 temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
994
995                 rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
996                 if (rc) {
997                         err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
998                         return;
999                 }       
1000         
1001                 rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
1002                 if (rc) {
1003                         err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
1004                         return;
1005                 }
1006                 
1007                 /* Clear command complete interrupt caused by this write */
1008                 temp_word = 0x1F;
1009                 rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
1010                 if (rc) {
1011                         err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
1012                         return;
1013                 }
1014         }
1015         return;
1016 }
1017
1018 static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
1019 {
1020         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
1021         enum pcie_link_speed lnk_speed;
1022         u32     lnk_cap;
1023         int retval = 0;
1024
1025         DBG_ENTER_ROUTINE 
1026
1027         if (!slot->ctrl->hpc_ctlr_handle) {
1028                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
1029                 return -1;
1030         }
1031
1032         if (slot->hp_slot >= php_ctlr->num_slots) {
1033                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
1034                 return -1;
1035         }
1036
1037         retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
1038
1039         if (retval) {
1040                 err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__);
1041                 return retval;
1042         }
1043
1044         switch (lnk_cap & 0x000F) {
1045         case 1:
1046                 lnk_speed = PCIE_2PT5GB;
1047                 break;
1048         default:
1049                 lnk_speed = PCIE_LNK_SPEED_UNKNOWN;
1050                 break;
1051         }
1052
1053         *value = lnk_speed;
1054         dbg("Max link speed = %d\n", lnk_speed);
1055         DBG_LEAVE_ROUTINE 
1056         return retval;
1057 }
1058
1059 static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value)
1060 {
1061         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
1062         enum pcie_link_width lnk_wdth;
1063         u32     lnk_cap;
1064         int retval = 0;
1065
1066         DBG_ENTER_ROUTINE 
1067
1068         if (!slot->ctrl->hpc_ctlr_handle) {
1069                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
1070                 return -1;
1071         }
1072
1073         if (slot->hp_slot >= php_ctlr->num_slots) {
1074                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
1075                 return -1;
1076         }
1077
1078         retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
1079
1080         if (retval) {
1081                 err("%s : hp_register_read_dword  LNK_CAP failed\n", __FUNCTION__);
1082                 return retval;
1083         }
1084
1085         switch ((lnk_cap & 0x03F0) >> 4){
1086         case 0:
1087                 lnk_wdth = PCIE_LNK_WIDTH_RESRV;
1088                 break;
1089         case 1:
1090                 lnk_wdth = PCIE_LNK_X1;
1091                 break;
1092         case 2:
1093                 lnk_wdth = PCIE_LNK_X2;
1094                 break;
1095         case 4:
1096                 lnk_wdth = PCIE_LNK_X4;
1097                 break;
1098         case 8:
1099                 lnk_wdth = PCIE_LNK_X8;
1100                 break;
1101         case 12:
1102                 lnk_wdth = PCIE_LNK_X12;
1103                 break;
1104         case 16:
1105                 lnk_wdth = PCIE_LNK_X16;
1106                 break;
1107         case 32:
1108                 lnk_wdth = PCIE_LNK_X32;
1109                 break;
1110         default:
1111                 lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
1112                 break;
1113         }
1114
1115         *value = lnk_wdth;
1116         dbg("Max link width = %d\n", lnk_wdth);
1117         DBG_LEAVE_ROUTINE 
1118         return retval;
1119 }
1120
1121 static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
1122 {
1123         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
1124         enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;
1125         int retval = 0;
1126         u16 lnk_status;
1127
1128         DBG_ENTER_ROUTINE 
1129
1130         if (!slot->ctrl->hpc_ctlr_handle) {
1131                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
1132                 return -1;
1133         }
1134
1135         if (slot->hp_slot >= php_ctlr->num_slots) {
1136                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
1137                 return -1;
1138         }
1139
1140         retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
1141
1142         if (retval) {
1143                 err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
1144                 return retval;
1145         }
1146
1147         switch (lnk_status & 0x0F) {
1148         case 1:
1149                 lnk_speed = PCIE_2PT5GB;
1150                 break;
1151         default:
1152                 lnk_speed = PCIE_LNK_SPEED_UNKNOWN;
1153                 break;
1154         }
1155
1156         *value = lnk_speed;
1157         dbg("Current link speed = %d\n", lnk_speed);
1158         DBG_LEAVE_ROUTINE 
1159         return retval;
1160 }
1161
1162 static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value)
1163 {
1164         struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle;
1165         enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
1166         int retval = 0;
1167         u16 lnk_status;
1168
1169         DBG_ENTER_ROUTINE 
1170
1171         if (!slot->ctrl->hpc_ctlr_handle) {
1172                 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
1173                 return -1;
1174         }
1175
1176         if (slot->hp_slot >= php_ctlr->num_slots) {
1177                 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
1178                 return -1;
1179         }
1180
1181         retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
1182
1183         if (retval) {
1184                 err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
1185                 return retval;
1186         }
1187         
1188         switch ((lnk_status & 0x03F0) >> 4){
1189         case 0:
1190                 lnk_wdth = PCIE_LNK_WIDTH_RESRV;
1191                 break;
1192         case 1:
1193                 lnk_wdth = PCIE_LNK_X1;
1194                 break;
1195         case 2:
1196                 lnk_wdth = PCIE_LNK_X2;
1197                 break;
1198         case 4:
1199                 lnk_wdth = PCIE_LNK_X4;
1200                 break;
1201         case 8:
1202                 lnk_wdth = PCIE_LNK_X8;
1203                 break;
1204         case 12:
1205                 lnk_wdth = PCIE_LNK_X12;
1206                 break;
1207         case 16:
1208                 lnk_wdth = PCIE_LNK_X16;
1209                 break;
1210         case 32:
1211                 lnk_wdth = PCIE_LNK_X32;
1212                 break;
1213         default:
1214                 lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
1215                 break;
1216         }
1217
1218         *value = lnk_wdth;
1219         dbg("Current link width = %d\n", lnk_wdth);
1220         DBG_LEAVE_ROUTINE 
1221         return retval;
1222 }
1223
1224 static struct hpc_ops pciehp_hpc_ops = {
1225         .power_on_slot          = hpc_power_on_slot,
1226         .power_off_slot         = hpc_power_off_slot,
1227         .set_attention_status   = hpc_set_attention_status,
1228         .get_power_status       = hpc_get_power_status,
1229         .get_attention_status   = hpc_get_attention_status,
1230         .get_latch_status       = hpc_get_latch_status,
1231         .get_adapter_status     = hpc_get_adapter_status,
1232
1233         .get_max_bus_speed      = hpc_get_max_lnk_speed,
1234         .get_cur_bus_speed      = hpc_get_cur_lnk_speed,
1235         .get_max_lnk_width      = hpc_get_max_lnk_width,
1236         .get_cur_lnk_width      = hpc_get_cur_lnk_width,
1237
1238         .query_power_fault      = hpc_query_power_fault,
1239         .green_led_on           = hpc_set_green_led_on,
1240         .green_led_off          = hpc_set_green_led_off,
1241         .green_led_blink        = hpc_set_green_led_blink,
1242         
1243         .release_ctlr           = hpc_release_ctlr,
1244         .check_lnk_status       = hpc_check_lnk_status,
1245 };
1246
1247 int pcie_init(struct controller * ctrl,
1248         struct pci_dev * pdev,
1249         php_intr_callback_t attention_button_callback,
1250         php_intr_callback_t switch_change_callback,
1251         php_intr_callback_t presence_change_callback,
1252         php_intr_callback_t power_fault_callback)
1253 {
1254         struct php_ctlr_state_s *php_ctlr, *p;
1255         void *instance_id = ctrl;
1256         int rc;
1257         static int first = 1;
1258         u16 temp_word;
1259         u16 cap_reg;
1260         u16 intr_enable;
1261         u32 slot_cap;
1262         int cap_base, saved_cap_base;
1263         u16 slot_status, slot_ctrl;
1264
1265         DBG_ENTER_ROUTINE
1266         
1267         spin_lock_init(&list_lock);
1268         php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
1269
1270         if (!php_ctlr) {        /* Allocate controller state data */
1271                 err("%s: HPC controller memory allocation error!\n", __FUNCTION__);
1272                 goto abort;
1273         }
1274
1275         memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s));
1276
1277         php_ctlr->pci_dev = pdev;       /* Save pci_dev in context */
1278
1279         dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__, 
1280                 pdev->vendor, pdev->device);
1281
1282         saved_cap_base = pcie_cap_base;
1283
1284         if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
1285                 dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
1286                 goto abort_free_ctlr;
1287         }
1288         pcie_cap_base = cap_base;
1289
1290         dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base);
1291
1292         rc = hp_register_read_word(pdev, CAP_REG, cap_reg);
1293         if (rc) {
1294                 err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
1295                 goto abort_free_ctlr;
1296         }
1297         dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, cap_reg);
1298
1299         if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 0x0040)){
1300                 dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__);
1301                 goto abort_free_ctlr;
1302         }
1303         
1304         rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
1305         if (rc) {
1306                 err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
1307                 goto abort_free_ctlr;
1308         }
1309         dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, slot_cap);
1310
1311         if (!(slot_cap & HP_CAP)) {
1312                 dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
1313                 goto abort_free_ctlr;
1314         }
1315
1316         /* For debugging purpose */
1317         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
1318         if (rc) {
1319                 err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
1320                 goto abort_free_ctlr;
1321         }
1322         dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
1323
1324         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
1325         if (rc) {
1326                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
1327                 goto abort_free_ctlr;
1328         }
1329         dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
1330
1331         if (first) {
1332                 spin_lock_init(&hpc_event_lock);
1333                 first = 0;
1334         }
1335
1336         dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, 
1337                 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq);
1338         for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
1339                 if (pci_resource_len(pdev, rc) > 0)
1340                         dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
1341                                 pci_resource_start(pdev, rc), pci_resource_len(pdev, rc));
1342
1343         dbg("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, 
1344                 pdev->subsystem_vendor, pdev->subsystem_device);
1345
1346         init_MUTEX(&ctrl->crit_sect);
1347         /* Setup wait queue */
1348         init_waitqueue_head(&ctrl->queue);
1349
1350         /* Find the IRQ */
1351         php_ctlr->irq = pdev->irq;
1352         dbg("HPC interrupt = %d\n", php_ctlr->irq);
1353
1354         /* Save interrupt callback info */
1355         php_ctlr->attention_button_callback = attention_button_callback;
1356         php_ctlr->switch_change_callback = switch_change_callback;
1357         php_ctlr->presence_change_callback = presence_change_callback;
1358         php_ctlr->power_fault_callback = power_fault_callback;
1359         php_ctlr->callback_instance_id = instance_id;
1360
1361         /* Return PCI Controller Info */
1362         php_ctlr->slot_device_offset = 0;
1363         php_ctlr->num_slots = 1;
1364
1365         /* Mask Hot-plug Interrupt Enable */
1366         rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
1367         if (rc) {
1368                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
1369                 goto abort_free_ctlr;
1370         }
1371         dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
1372         temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
1373
1374         rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
1375         if (rc) {
1376                 err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
1377                 goto abort_free_ctlr;
1378         }
1379         dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
1380         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
1381         if (rc) {
1382                 err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
1383                 goto abort_free_ctlr;
1384         }
1385         dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, 
1386                 SLOT_STATUS, slot_status);
1387         
1388         temp_word = 0x1F; /* Clear all events */
1389         rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
1390         if (rc) {
1391                 err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
1392                 goto abort_free_ctlr;
1393         }
1394         dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
1395
1396         if (pciehp_poll_mode)  {/* Install interrupt polling code */
1397                 /* Install and start the interrupt polling timer */
1398                 init_timer(&php_ctlr->int_poll_timer);
1399                 start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
1400         } else {
1401                 /* Installs the interrupt handler */
1402                 rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
1403                 dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
1404                 if (rc) {
1405                         err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
1406                         goto abort_free_ctlr;
1407                 }
1408         }
1409
1410         rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
1411         if (rc) {
1412                 err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
1413                 goto abort_free_ctlr;
1414         }
1415         dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
1416
1417         intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
1418                         PRSN_DETECT_ENABLE;
1419
1420         temp_word = (temp_word & ~intr_enable) | intr_enable; 
1421
1422         if (pciehp_poll_mode) {
1423                 temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
1424         } else {
1425                 temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
1426         }
1427         dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
1428
1429         /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
1430         rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
1431         if (rc) {
1432                 err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
1433                 goto abort_free_ctlr;
1434         }
1435         dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
1436         
1437         rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
1438         if (rc) {
1439                 err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
1440                 goto abort_free_ctlr;
1441         }
1442         dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, 
1443                 SLOT_STATUS, slot_status);
1444         
1445         temp_word =  0x1F; /* Clear all events */
1446         rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
1447         if (rc) {
1448                 err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
1449                 goto abort_free_ctlr;
1450         }
1451         dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
1452         
1453         /*  Add this HPC instance into the HPC list */
1454         spin_lock(&list_lock);
1455         if (php_ctlr_list_head == 0) {
1456                 php_ctlr_list_head = php_ctlr;
1457                 p = php_ctlr_list_head;
1458                 p->pnext = 0;
1459         } else {
1460                 p = php_ctlr_list_head;
1461
1462                 while (p->pnext)
1463                         p = p->pnext;
1464
1465                 p->pnext = php_ctlr;
1466         }
1467         spin_unlock(&list_lock);
1468
1469         ctlr_seq_num++;
1470         ctrl->hpc_ctlr_handle = php_ctlr;
1471         ctrl->hpc_ops = &pciehp_hpc_ops;
1472
1473         DBG_LEAVE_ROUTINE
1474         return 0;
1475
1476         /* We end up here for the many possible ways to fail this API.  */
1477 abort_free_ctlr:
1478         pcie_cap_base = saved_cap_base;
1479         kfree(php_ctlr);
1480 abort:
1481         DBG_LEAVE_ROUTINE
1482         return -1;
1483 }