linux-old/drivers/hotplug/pciehp_hpc.c
<<
>>
Prefs
   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
  74struct 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 */
  93enum 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};
 109static 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
 219struct 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
 235static spinlock_t hpc_event_lock;
 236
 237DEFINE_DBG_BUFFER               /* Debug string buffer for entire HPC defined here */
 238static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */
 239static int ctlr_seq_num = 0;    /* Controller sequence # */
 240static spinlock_t list_lock;
 241static void pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
 242
 243static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
 244
 245/* This is the interrupt polling timeout function. */
 246static 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. */
 271static 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
 289static 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
 329static 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
 361static 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
 409static 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
 450static 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
 476static 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
 504static 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
 533static 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
 585static 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
 623static 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
 661static 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
 699int 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
 733static 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
 779static 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
 828static 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
 878static 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
1018static 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
1059static 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
1121static 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
1162static 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
1224static 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
1247int 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.  */
1477abort_free_ctlr:
1478        pcie_cap_base = saved_cap_base;
1479        kfree(php_ctlr);
1480abort:
1481        DBG_LEAVE_ROUTINE
1482        return -1;
1483}
1484
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.