linux-old/drivers/pcmcia/i82092.c
<<
>>
Prefs
   1/* 
   2 * Driver for Intel I82092AA PCI-PCMCIA bridge.
   3 *
   4 * (C) 2001-2003 Red Hat, Inc.
   5 *
   6 * Author: Arjan Van De Ven <arjanv@redhat.com> 
   7 * Loosely based on i82365.c from the pcmcia-cs package
   8 *
   9 * $Id: i82092.c,v 1.16 2003/04/15 16:36:42 dwmw2 Exp $
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/config.h>
  14#include <linux/module.h>
  15#include <linux/pci.h>
  16#include <linux/init.h>
  17#include <linux/sched.h>
  18#include <linux/tqueue.h>
  19
  20#include <pcmcia/cs_types.h>
  21#include <pcmcia/ss.h>
  22#include <pcmcia/cs.h>
  23
  24#include <asm/system.h>
  25#include <asm/io.h>
  26
  27#include "i82092aa.h"
  28#include "i82365.h"
  29
  30MODULE_LICENSE("GPL");
  31MODULE_AUTHOR("Red Hat, Inc. - Arjan Van De Ven <arjanv@redhat.com>");
  32MODULE_DESCRIPTION("Socket driver for Intel i82092AA PCI-PCMCIA bridge");
  33
  34/* Extra i82092-specific register */
  35#define I365_CPAGE 0x26
  36
  37/* PCI core routines */
  38static struct pci_device_id i82092aa_pci_ids[] = {
  39        {
  40              vendor:PCI_VENDOR_ID_INTEL,
  41              device:PCI_DEVICE_ID_INTEL_82092AA_0,
  42              subvendor:PCI_ANY_ID,
  43              subdevice:PCI_ANY_ID,
  44              class: 0, class_mask:0,
  45
  46         },
  47         {} 
  48};
  49
  50static struct pci_driver i82092aa_pci_drv = {
  51        name:           "i82092aa",
  52        id_table:       i82092aa_pci_ids,
  53        probe:          i82092aa_pci_probe,
  54        remove:         __devexit_p(i82092aa_pci_remove),
  55        suspend:        NULL,
  56        resume:         NULL 
  57};
  58
  59
  60/* the pccard structure and its functions */
  61static struct pccard_operations i82092aa_operations = {
  62        init:                   i82092aa_init,
  63        suspend:                i82092aa_suspend,
  64        register_callback:      i82092aa_register_callback,
  65        inquire_socket:         i82092aa_inquire_socket,   
  66        get_status:             i82092aa_get_status,
  67        get_socket:             i82092aa_get_socket,
  68        set_socket:             i82092aa_set_socket,
  69        get_io_map:             i82092aa_get_io_map,
  70        set_io_map:             i82092aa_set_io_map,
  71        get_mem_map:            i82092aa_get_mem_map,
  72        set_mem_map:            i82092aa_set_mem_map,
  73        proc_setup:             i82092aa_proc_setup,
  74};
  75
  76/* The card can do upto 4 sockets, allocate a structure for each of them */
  77
  78struct socket_info {
  79        int     card_state;     /*  0 = no socket,
  80                                    1 = empty socket, 
  81                                    2 = card but not initialized,
  82                                    3 = operational card */
  83        unsigned long io_base;  /* base io address of the socket */
  84        socket_cap_t cap;
  85
  86        unsigned int pending_events; /* Pending events on this interface */
  87        
  88        void    (*handler)(void *info, u_int events); 
  89                                /* callback to the driver of the card */
  90        void    *info;          /* to be passed to the handler */
  91        
  92        struct pci_dev *dev;    /* The PCI device for the socket */
  93};
  94
  95#define MAX_SOCKETS 4
  96static struct socket_info sockets[MAX_SOCKETS];
  97static int socket_count;  /* shortcut */
  98
  99int membase = -1;
 100int isa_setup;
 101
 102MODULE_PARM(membase, "i");
 103MODULE_PARM(isa_setup, "i");
 104
 105static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 106{
 107        unsigned char configbyte;
 108        struct pci_dev *parent;
 109        int i;
 110        
 111        enter("i82092aa_pci_probe");
 112        
 113        if (pci_enable_device(dev))
 114                return -EIO;
 115
 116        /* Since we have no memory BARs some firmware we may not
 117           have had PCI_COMMAND_MEM enabled, yet the device needs
 118           it. */
 119        pci_read_config_byte(dev, PCI_COMMAND, &configbyte);
 120        if (!(configbyte | PCI_COMMAND_MEMORY)) {
 121                dprintk(KERN_DEBUG "Enabling PCI_COMMAND_MEMORY\n");
 122                configbyte |= PCI_COMMAND_MEMORY;
 123                pci_write_config_byte(dev, PCI_COMMAND, configbyte);
 124        }
 125
 126        pci_read_config_byte(dev, 0x40, &configbyte);  /* PCI Configuration Control */
 127        switch(configbyte&6) {
 128                case 0:
 129                        printk(KERN_INFO "i82092aa: configured as a 2 socket device.\n");
 130                        socket_count = 2;
 131                        break;
 132                case 2:
 133                        printk(KERN_INFO "i82092aa: configured as a 1 socket device.\n");
 134                        socket_count = 1;
 135                        break;
 136                case 4:
 137                case 6:
 138                        printk(KERN_INFO "i82092aa: configured as a 4 socket device.\n");
 139                        socket_count = 4;
 140                        break;
 141                        
 142                default:
 143                        printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.\n");
 144                        return -EIO;
 145                        break;
 146        }
 147        
 148        if (membase == -1) {
 149                for (i = 0; i < 4; i++) {
 150                        if ((dev->bus->resource[i]->flags & (IORESOURCE_MEM|IORESOURCE_READONLY|IORESOURCE_CACHEABLE|IORESOURCE_SHADOWABLE))
 151                            == IORESOURCE_MEM) {
 152                                membase = dev->bus->resource[i]->start >> 24;
 153                                goto mem_ok;
 154                        }
 155                }
 156                printk(KERN_WARNING "No suitable memory range for i82092aa found\n");
 157                return -ENOSPC;
 158        }
 159 mem_ok:
 160        if (membase)
 161                printk(KERN_NOTICE "i82092 memory base address set to 0x%02x000000\n", membase);
 162
 163        /* If we're down the end of the PCI bus chain where ISA cycles don't get sent, then
 164           only 1/4 of the I/O address space is going to be usable, unless we make sure that
 165           the NO_ISA bit in the Bridge Control register of all upstream busses is cleared.
 166           Since some PCMCIA cards (most serial ports, for example) will decode 10 bits and
 167           respond only to addresses where bits 8 and 9 are non-zero, we need to do this. */
 168        for (parent = dev->bus->self; 
 169             parent && (parent->class>>8) == PCI_CLASS_BRIDGE_PCI;
 170             parent = parent->bus->self) {
 171                uint16_t brctl;
 172
 173                if (pci_read_config_word(parent, PCI_BRIDGE_CONTROL, &brctl)) {
 174                        printk(KERN_WARNING "Error reading bridge control word from device %s\n", parent->slot_name);
 175                        continue;
 176                }
 177
 178                if (!(brctl & PCI_BRIDGE_CTL_NO_ISA))
 179                        continue;
 180
 181                if (isa_setup) {
 182                        printk(KERN_NOTICE "PCI bridge %s has NOISA bit set. Clearing to allow full PCMCIA operation\n",
 183                               parent->slot_name);
 184                        brctl &= ~PCI_BRIDGE_CTL_NO_ISA;
 185                        if (pci_write_config_word(parent, PCI_BRIDGE_CONTROL, brctl))
 186                                printk(KERN_WARNING "Error writing bridge control word from device %s\n", parent->slot_name);
 187                } else {
 188                        printk(KERN_NOTICE "PCI bridge %s has NOISA bit set. Some I/O addresses for PCMCIA cards will not work.\n",
 189                               parent->slot_name);
 190                        printk(KERN_NOTICE "Perhaps use 'isa_setup=1' option to i82092.o?\n");
 191                        break;
 192                }
 193        }                       
 194                                
 195        for (i = 0;i<socket_count;i++) {
 196                sockets[i].card_state = 1; /* 1 = present but empty */
 197                sockets[i].io_base = (dev->resource[0].start & ~1);
 198                 if (sockets[i].io_base > 0) 
 199                        request_region(sockets[i].io_base, 2, "i82092aa");
 200                 
 201                
 202                sockets[i].cap.features |= SS_CAP_PCCARD | SS_CAP_PAGE_REGS;
 203                sockets[i].cap.map_size = 0x1000;
 204                sockets[i].cap.irq_mask = 0;
 205                sockets[i].cap.pci_irq  = dev->irq;
 206
 207                /* Trick the resource code into doing the right thing... */
 208                sockets[i].cap.cb_dev = dev;
 209                
 210                if (card_present(i)) {
 211                        sockets[i].card_state = 3;
 212                        dprintk(KERN_DEBUG "i82092aa: slot %i is occupied\n",i);
 213                } else {
 214                        dprintk(KERN_DEBUG "i82092aa: slot %i is vacant\n",i);
 215                }
 216        }
 217                
 218        /* Now, specifiy that all interrupts are to be done as PCI interrupts */
 219        configbyte = 0xFF; /* bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt */
 220        pci_write_config_byte(dev, 0x50, configbyte); /* PCI Interrupt Routing Register */
 221
 222
 223        /* Register the interrupt handler */
 224        dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq);
 225        if (request_irq(dev->irq, i82092aa_interrupt, SA_SHIRQ, "i82092aa", i82092aa_interrupt)) {
 226                printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq);
 227                return -EIO;
 228        }
 229                 
 230        
 231        if (register_ss_entry(socket_count, &i82092aa_operations) != 0)
 232                printk(KERN_NOTICE "i82092aa: register_ss_entry() failed\n");
 233
 234        leave("i82092aa_pci_probe");
 235        return 0;
 236}
 237
 238static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
 239{
 240        enter("i82092aa_pci_remove");
 241        
 242        free_irq(dev->irq, i82092aa_interrupt);
 243
 244        leave("i82092aa_pci_remove");
 245}
 246
 247static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
 248
 249/* basic value read/write functions */
 250
 251static unsigned char indirect_read(int socket, unsigned short reg)
 252{
 253        unsigned long port;
 254        unsigned char val;
 255        unsigned long flags;
 256        spin_lock_irqsave(&port_lock,flags);
 257        reg += socket * 0x40;
 258        port = sockets[socket].io_base;
 259        outb(reg,port);
 260        val = inb(port+1);
 261        spin_unlock_irqrestore(&port_lock,flags);
 262        return val;
 263}
 264
 265static unsigned short indirect_read16(int socket, unsigned short reg)
 266{
 267        unsigned long port;
 268        unsigned short tmp;
 269        unsigned long flags;
 270        spin_lock_irqsave(&port_lock,flags);
 271        reg  = reg + socket * 0x40;
 272        port = sockets[socket].io_base;
 273        outb(reg,port);
 274        tmp = inb(port+1);
 275        reg++;
 276        outb(reg,port);
 277        tmp = tmp | (inb(port+1)<<8);
 278        spin_unlock_irqrestore(&port_lock,flags);
 279        return tmp;
 280}
 281
 282static void indirect_write(int socket, unsigned short reg, unsigned char value)
 283{
 284        unsigned long port;
 285        unsigned long flags;
 286        spin_lock_irqsave(&port_lock,flags);
 287        reg = reg + socket * 0x40;
 288        port = sockets[socket].io_base; 
 289        outb(reg,port);
 290        outb(value,port+1);
 291        spin_unlock_irqrestore(&port_lock,flags);
 292}
 293
 294static void indirect_setbit(int socket, unsigned short reg, unsigned char mask)
 295{
 296        unsigned long port;
 297        unsigned char val;
 298        unsigned long flags;
 299        spin_lock_irqsave(&port_lock,flags);
 300        reg = reg + socket * 0x40;
 301        port = sockets[socket].io_base; 
 302        outb(reg,port);
 303        val = inb(port+1);
 304        val |= mask;
 305        outb(reg,port);
 306        outb(val,port+1);
 307        spin_unlock_irqrestore(&port_lock,flags);
 308}
 309
 310
 311static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask)
 312{
 313        unsigned long port;
 314        unsigned char val;
 315        unsigned long flags;
 316        spin_lock_irqsave(&port_lock,flags);
 317        reg = reg + socket * 0x40;
 318        port = sockets[socket].io_base; 
 319        outb(reg,port);
 320        val = inb(port+1);
 321        val &= ~mask;
 322        outb(reg,port);
 323        outb(val,port+1);
 324        spin_unlock_irqrestore(&port_lock,flags);
 325}
 326
 327static void indirect_write16(int socket, unsigned short reg, unsigned short value)
 328{
 329        unsigned long port;
 330        unsigned char val;
 331        unsigned long flags;
 332        spin_lock_irqsave(&port_lock,flags);
 333        reg = reg + socket * 0x40;
 334        port = sockets[socket].io_base; 
 335        
 336        outb(reg,port);
 337        val = value & 255;
 338        outb(val,port+1);
 339        
 340        reg++;
 341        
 342        outb(reg,port);
 343        val = value>>8;
 344        outb(val,port+1);
 345        spin_unlock_irqrestore(&port_lock,flags);
 346}
 347
 348/* simple helper functions */
 349/* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
 350static int cycle_time = 120;
 351
 352static int to_cycles(int ns)
 353{
 354        if (cycle_time!=0)
 355                return ns/cycle_time;
 356        else
 357                return 0;
 358}
 359    
 360static int to_ns(int cycles)
 361{
 362        return cycle_time*cycles;
 363}
 364
 365
 366/* Interrupt handler functionality */
 367
 368static void i82092aa_bh(void *dummy)
 369{
 370        unsigned int events;
 371        int i;
 372                
 373        for (i=0; i < socket_count; i++) {
 374                events = xchg(&(sockets[i].pending_events),0);
 375                dprintk("events = %x \n",events);
 376                if (sockets[i].handler)
 377                        sockets[i].handler(sockets[i].info, events);
 378        }
 379}
 380                                                                                                                                        
 381
 382static struct tq_struct i82092aa_task = {
 383        routine:        i82092aa_bh
 384};
 385        
 386
 387static void i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
 388{
 389        int i;
 390        int loopcount = 0;
 391        
 392        unsigned int events, active=0;
 393        
 394/*      enter("i82092aa_interrupt");*/
 395        
 396        while (1) {
 397                loopcount++;
 398                if (loopcount>20) {
 399                        printk(KERN_ERR "i82092aa: infinite eventloop in interrupt \n");
 400                        break;
 401                }
 402                
 403                active = 0;
 404                
 405                for (i=0;i<socket_count;i++) {
 406                        int csc;
 407                        if (sockets[i].card_state==0) /* Inactive socket, should not happen */
 408                                continue;
 409                        
 410                        csc = indirect_read(i,I365_CSC); /* card status change register */
 411                        
 412                        if ((csc==0) ||  /* no events on this socket */
 413                           (sockets[i].handler==NULL)) /* no way to handle events */
 414                                continue;
 415                        events = 0;
 416                         
 417                        if (csc & I365_CSC_DETECT) {
 418                                events |= SS_DETECT;
 419                                dprintk("Card detected in socket %i!\n",i);
 420                         }
 421                        
 422                        if (indirect_read(i,I365_INTCTL) & I365_PC_IOCARD) { 
 423                                /* For IO/CARDS, bit 0 means "read the card" */
 424                                events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 
 425                        } else {
 426                                /* Check for battery/ready events */
 427                                events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
 428                                events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
 429                                events |= (csc & I365_CSC_READY) ? SS_READY : 0;
 430                        }
 431                        
 432                        if (events) {
 433                                sockets[i].pending_events |= events;
 434                                schedule_task(&i82092aa_task);
 435                        }
 436                        active |= events;
 437                }
 438                                
 439                if (active==0) /* no more events to handle */
 440                        break;                          
 441                
 442        }
 443        
 444/*      leave("i82092aa_interrupt");*/
 445}
 446
 447
 448
 449/* socket functions */
 450
 451static int card_present(int socketno)
 452{       
 453        unsigned int val;
 454        enter("card_present");
 455        
 456        if ((socketno<0) || (socketno > MAX_SOCKETS))
 457                return 0;
 458        if (sockets[socketno].io_base == 0)
 459                return 0;
 460
 461                
 462        val = indirect_read(socketno, 1); /* Interface status register */
 463        if ((val&12)==12) {
 464                leave("card_present 1");
 465                return 1;
 466        }
 467                
 468        leave("card_present 0");
 469        return 0;
 470}
 471
 472static void set_bridge_state(int sock)
 473{
 474        enter("set_bridge_state");
 475        indirect_write(sock, I365_GBLCTL,0x00);
 476        indirect_write(sock, I365_GENCTL,0x00);
 477        
 478        indirect_setbit(sock, I365_INTCTL,0x08);
 479        leave("set_bridge_state");
 480}
 481
 482
 483
 484
 485
 486      
 487static int i82092aa_init(unsigned int s)
 488{
 489        int i;
 490        pccard_io_map io = { 0, 0, 0, 0, 1 };
 491        pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
 492        
 493        enter("i82092aa_init");
 494                        
 495        i82092aa_set_socket(s, &dead_socket);
 496        for (i = 0; i < 2; i++) {
 497                io.map = i;
 498                i82092aa_set_io_map(s, &io);
 499        }
 500        for (i = 0; i < 5; i++) {
 501                mem.map = i;
 502                i82092aa_set_mem_map(s, &mem);
 503        }
 504        
 505        leave("i82092aa_init");
 506        return 0;
 507}
 508                                                                                                                                                                                                                                              
 509static int i82092aa_suspend(unsigned int sock)
 510{
 511        int retval;
 512        enter("i82092aa_suspend");
 513        retval =  i82092aa_set_socket(sock, &dead_socket);
 514        leave("i82092aa_suspend");
 515        return retval;
 516}
 517       
 518static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
 519{
 520        enter("i82092aa_register_callback");
 521        sockets[sock].handler = handler;
 522        sockets[sock].info = info;
 523        if (handler == NULL) {   
 524                MOD_DEC_USE_COUNT;   
 525        } else {
 526                MOD_INC_USE_COUNT;
 527        }
 528        leave("i82092aa_register_callback");
 529        return 0;
 530} /* i82092aa_register_callback */
 531                                        
 532static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
 533{
 534        enter("i82092aa_inquire_socket");
 535        *cap = sockets[sock].cap;
 536        leave("i82092aa_inquire_socket");
 537        return 0;
 538} /* i82092aa_inquire_socket */
 539
 540
 541static int i82092aa_get_status(unsigned int sock, u_int *value)
 542{
 543        unsigned int status;
 544        
 545        enter("i82092aa_get_status");
 546        
 547        status = indirect_read(sock,I365_STATUS); /* Interface Status Register */
 548        *value = 0;
 549        
 550        if ((status & I365_CS_DETECT) == I365_CS_DETECT) {
 551                *value |= SS_DETECT;
 552        }
 553                
 554        /* IO cards have a different meaning of bits 0,1 */
 555        /* Also notice the inverse-logic on the bits */
 556         if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) {
 557                /* IO card */
 558                if (!(status & I365_CS_STSCHG))
 559                        *value |= SS_STSCHG;
 560         } else { /* non I/O card */
 561                if (!(status & I365_CS_BVD1))
 562                        *value |= SS_BATDEAD;
 563                if (!(status & I365_CS_BVD2))
 564                        *value |= SS_BATWARN;
 565                        
 566         }
 567         
 568         if (status & I365_CS_WRPROT)
 569                (*value) |= SS_WRPROT;  /* card is write protected */
 570         
 571         if (status & I365_CS_READY)
 572                (*value) |= SS_READY;    /* card is not busy */
 573                
 574         if (status & I365_CS_POWERON)
 575                (*value) |= SS_POWERON;  /* power is applied to the card */
 576
 577
 578        leave("i82092aa_get_status");
 579        return 0;
 580}
 581
 582
 583static int i82092aa_get_socket(unsigned int sock, socket_state_t *state) 
 584{
 585        unsigned char reg,vcc,vpp;
 586        
 587        enter("i82092aa_get_socket");
 588        state->flags    = 0;
 589        state->Vcc      = 0;
 590        state->Vpp      = 0;
 591        state->io_irq   = 0;
 592        state->csc_mask = 0;
 593
 594        /* First the power status of the socket */
 595        reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */
 596
 597        if (reg & I365_PWR_AUTO)
 598                state->flags |= SS_PWR_AUTO;  /* Automatic Power Switch */
 599                
 600        if (reg & I365_PWR_OUT)
 601                state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
 602                
 603        vcc = reg & I365_VCC_MASK;    vpp = reg & I365_VPP1_MASK;
 604        
 605        if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */
 606                state->Vcc = 50;
 607                
 608                if (vpp == I365_VPP1_5V)
 609                        state->Vpp = 50;
 610                if (vpp == I365_VPP1_12V)
 611                        state->Vpp = 120;
 612                        
 613        }
 614        
 615        if ((reg & I365_VCC_3V)==I365_VCC_3V)
 616                state->Vcc = 33;
 617        
 618        
 619        /* Now the IO card, RESET flags and IO interrupt */
 620        
 621        reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */
 622        
 623        if ((reg & I365_PC_RESET)==0)
 624                state->flags |= SS_RESET;
 625        if (reg & I365_PC_IOCARD) 
 626                state->flags |= SS_IOCARD; /* This is an IO card */
 627        
 628        /* Set the IRQ number */
 629        if (sockets[sock].dev!=NULL)
 630                state->io_irq = sockets[sock].dev->irq;
 631        
 632        /* Card status change */
 633        reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */
 634        
 635        if (reg & I365_CSC_DETECT) 
 636                state->csc_mask |= SS_DETECT; /* Card detect is enabled */
 637        
 638        if (state->flags & SS_IOCARD) {/* IO Cards behave different */
 639                if (reg & I365_CSC_STSCHG)
 640                        state->csc_mask |= SS_STSCHG;
 641        } else {
 642                if (reg & I365_CSC_BVD1) 
 643                        state->csc_mask |= SS_BATDEAD;
 644                if (reg & I365_CSC_BVD2) 
 645                        state->csc_mask |= SS_BATWARN;
 646                if (reg & I365_CSC_READY) 
 647                        state->csc_mask |= SS_READY;
 648        }
 649                
 650        leave("i82092aa_get_socket");
 651        return 0;
 652}
 653
 654static int i82092aa_set_socket(unsigned int sock, socket_state_t *state) 
 655{
 656        unsigned char reg;
 657        
 658        enter("i82092aa_set_socket");
 659        
 660        /* First, set the global controller options */
 661        
 662        set_bridge_state(sock);
 663        
 664        /* Values for the IGENC register */
 665        
 666        reg = 0;
 667        if (!(state->flags & SS_RESET))         /* The reset bit has "inverse" logic */
 668                reg = reg | I365_PC_RESET;  
 669        if (state->flags & SS_IOCARD) 
 670                reg = reg | I365_PC_IOCARD;
 671                
 672        indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */
 673        
 674        /* Power registers */
 675        
 676        reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
 677        
 678        if (state->flags & SS_PWR_AUTO) {
 679                dprintk("Auto power\n");
 680                reg |= I365_PWR_AUTO;   /* automatic power mngmnt */
 681        }
 682        if (state->flags & SS_OUTPUT_ENA) {
 683                dprintk("Power Enabled \n");
 684                reg |= I365_PWR_OUT;    /* enable power */
 685        }
 686        
 687        switch (state->Vcc) {
 688                case 0: 
 689                        break;
 690                case 50: 
 691                        dprintk("setting voltage to Vcc to 5V on socket %i\n",sock);
 692                        reg |= I365_VCC_5V;
 693                        break;
 694                default:
 695                        printk(KERN_WARNING "i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc);
 696                        leave("i82092aa_set_socket");
 697                        return -EINVAL;
 698        }
 699        
 700        
 701        switch (state->Vpp) {
 702                case 0: 
 703                        dprintk("not setting Vpp on socket %i\n",sock);
 704                        break;
 705                case 50: 
 706                        dprintk("setting Vpp to 5.0 for socket %i\n",sock);
 707                        reg |= I365_VPP1_5V | I365_VPP2_5V;
 708                        break;
 709                case 120: 
 710                        dprintk("setting Vpp to 12.0\n");
 711                        reg |= I365_VPP1_12V | I365_VPP2_12V;
 712                        break;
 713                default:
 714                        printk(KERN_WARNING "i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc);
 715                        leave("i82092aa_set_socket");
 716                        return -EINVAL;
 717        }
 718        
 719        if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */
 720                indirect_write(sock,I365_POWER,reg);
 721                
 722        /* Enable specific interrupt events */
 723        
 724        reg = 0x00;
 725        if (state->csc_mask & SS_DETECT) {
 726                reg |= I365_CSC_DETECT;
 727        }
 728        if (state->flags & SS_IOCARD) {
 729                if (state->csc_mask & SS_STSCHG)
 730                        reg |= I365_CSC_STSCHG;
 731        } else {
 732                if (state->csc_mask & SS_BATDEAD) 
 733                        reg |= I365_CSC_BVD1;
 734                if (state->csc_mask & SS_BATWARN) 
 735                        reg |= I365_CSC_BVD2;
 736                if (state->csc_mask & SS_READY) 
 737                        reg |= I365_CSC_READY; 
 738                                        
 739        }
 740        
 741        /* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/
 742        
 743        indirect_write(sock,I365_CSCINT,reg);
 744        (void)indirect_read(sock,I365_CSC);
 745
 746        leave("i82092aa_set_socket");
 747        return 0;
 748}
 749
 750static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io)
 751{
 752        unsigned char map, ioctl, addr;
 753        
 754        enter("i82092aa_get_io_map");
 755        map = io->map;
 756        if (map > 1) {
 757                leave("i82092aa_get_io_map with -EINVAL");
 758                return -EINVAL;
 759        }
 760        
 761        /* FIXME: How does this fit in with the PCI resource (re)allocation */
 762        io->start = indirect_read16(sock, I365_IO(map)+I365_W_START);
 763        io->stop  = indirect_read16(sock, I365_IO(map)+I365_W_START);
 764        
 765        ioctl = indirect_read(sock,I365_IOCTL); /* IOCREG: I/O Control Register */
 766        addr  = indirect_read(sock,I365_ADDRWIN); /* */
 767        
 768        io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; /* check this out later */
 769        io->flags = 0;
 770        
 771        if (addr & I365_IOCTL_16BIT(map))
 772                io->flags |= MAP_AUTOSZ;
 773                
 774        leave("i82092aa_get_io_map");
 775        return 0;
 776}
 777
 778static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
 779{
 780        unsigned char map, ioctl;
 781        
 782        enter("i82092aa_set_io_map");
 783        
 784        map = io->map;
 785        
 786        /* Check error conditions */    
 787        if (map > 1) {
 788                leave("i82092aa_set_io_map with invalid map");
 789                return -EINVAL;
 790        }
 791        if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){
 792                leave("i82092aa_set_io_map with invalid io");
 793                return -EINVAL;
 794        }
 795
 796        /* Turn off the window before changing anything */ 
 797        if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map))
 798                indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map));
 799
 800/*      printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop);  */
 801        
 802        /* write the new values */
 803        indirect_write16(sock,I365_IO(map)+I365_W_START,io->start);             
 804        indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop);               
 805                        
 806        ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map);
 807        
 808        if (io->flags & (MAP_16BIT|MAP_AUTOSZ))
 809                ioctl |= I365_IOCTL_16BIT(map);
 810                
 811        indirect_write(sock,I365_IOCTL,ioctl);
 812        
 813        /* Turn the window back on if needed */
 814        if (io->flags & MAP_ACTIVE)
 815                indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map));
 816                        
 817        leave("i82092aa_set_io_map");   
 818        return 0;
 819}
 820
 821static int i82092aa_get_mem_map(unsigned sock, struct pccard_mem_map *mem)
 822{
 823        unsigned short base, i;
 824        unsigned char map, addr;
 825        
 826        enter("i82092aa_get_mem_map");
 827        
 828        mem->flags = 0;
 829        mem->speed = 0;
 830        map = mem->map;
 831        if (map > 4) {
 832                leave("i82092aa_get_mem_map: -EINVAL");
 833                return -EINVAL;
 834        }
 835        
 836        addr = indirect_read(sock, I365_ADDRWIN);
 837                
 838        if (addr & I365_ENA_MEM(map))
 839                mem->flags |= MAP_ACTIVE;               /* yes this mapping is active */
 840        
 841        base = I365_MEM(map); 
 842        
 843        /* Find the start address - this register also has mapping info */
 844        
 845        i = indirect_read16(sock,base+I365_W_START);
 846        if (i & I365_MEM_16BIT)
 847                mem->flags |= MAP_16BIT;
 848        if (i & I365_MEM_0WS)
 849                mem->flags |= MAP_0WS;
 850        
 851        mem->sys_start = ((unsigned long)(i & 0x0fff) << 12);
 852        
 853        /* Find the end address - this register also has speed info */
 854        i = indirect_read16(sock,base+I365_W_STOP);
 855        if (i & I365_MEM_WS0)
 856                mem->speed = 1;
 857        if (i & I365_MEM_WS1)
 858                mem->speed += 2;
 859        mem->speed = to_ns(mem->speed);
 860        mem->sys_stop = ( (unsigned long)(i & 0x0fff) << 12) + 0x0fff;
 861        
 862        /* Find the card start address, also some more MAP attributes */
 863        
 864        i = indirect_read16(sock, base+I365_W_OFF);
 865        if (i & I365_MEM_WRPROT)
 866                mem->flags |= MAP_WRPROT;
 867        if (i & I365_MEM_REG)
 868                mem->flags |= MAP_ATTRIB;
 869        mem->card_start = ( (unsigned long)(i & 0x3fff)<12) + mem->sys_start;
 870        mem->card_start &=  0x3ffffff;
 871        
 872        dprintk("Card %i is from %lx to %lx \n",sock,mem->sys_start,mem->sys_stop);
 873        
 874        leave("i82092aa_get_mem_map");
 875        return 0;
 876        
 877}
 878
 879static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
 880{
 881        unsigned short base, i;
 882        unsigned char map;
 883
 884        enter("i82092aa_set_mem_map");
 885        
 886        map = mem->map;
 887        if (map > 4) {
 888                leave("i82092aa_set_mem_map: invalid map");
 889                return -EINVAL;
 890        }
 891        
 892        /* Turn off the window before changing anything */
 893        if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
 894                      indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
 895
 896        
 897        if (!(mem->flags & MAP_ACTIVE))
 898                return 0;
 899
 900        if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) ||
 901             ((mem->sys_start >> 24) != membase) || ((mem->sys_stop >> 24) != membase) ||
 902             (mem->speed > 1000) ) {
 903                leave("i82092aa_set_mem_map: invalid address / speed");
 904                printk(KERN_WARNING "invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start);
 905                return -EINVAL;
 906        }
 907        
 908                         
 909                         
 910/*      printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE);  */
 911
 912        /* write the start address */
 913        base = I365_MEM(map);
 914        i = (mem->sys_start >> 12) & 0x0fff;
 915        if (mem->flags & MAP_16BIT) 
 916                i |= I365_MEM_16BIT;
 917        if (mem->flags & MAP_0WS)
 918                i |= I365_MEM_0WS;      
 919        indirect_write16(sock,base+I365_W_START,i);
 920                               
 921        /* write the stop address */
 922        
 923        i= (mem->sys_stop >> 12) & 0x0fff;
 924        switch (to_cycles(mem->speed)) {
 925                case 0:
 926                        break;
 927                case 1:
 928                        i |= I365_MEM_WS0;
 929                        break;
 930                case 2:
 931                        i |= I365_MEM_WS1;
 932                        break;
 933                default:
 934                        i |= I365_MEM_WS1 | I365_MEM_WS0;
 935                        break;
 936        }
 937        
 938        indirect_write16(sock,base+I365_W_STOP,i);
 939        
 940        /* card start */
 941        
 942        i = (((mem->card_start - mem->sys_start) >> 12) - (membase << 12)) & 0x3fff;
 943        if (mem->flags & MAP_WRPROT)
 944                i |= I365_MEM_WRPROT;
 945        if (mem->flags & MAP_ATTRIB) {
 946/*              printk("requesting attribute memory for socket %i\n",sock);*/
 947                i |= I365_MEM_REG;
 948        } else {
 949/*              printk("requesting normal memory for socket %i\n",sock);*/
 950        }
 951        indirect_write16(sock,base+I365_W_OFF,i);
 952        indirect_write(sock, I365_CPAGE, membase);
 953
 954        /* Enable the window if necessary */
 955        indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
 956                    
 957        leave("i82092aa_set_mem_map");
 958        return 0;
 959}
 960
 961static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
 962{
 963        
 964}
 965/* Module stuff */
 966
 967static int i82092aa_module_init(void)
 968{
 969        enter("i82092aa_module_init");
 970        pci_register_driver(&i82092aa_pci_drv);
 971        leave("i82092aa_module_init");
 972        return 0;
 973}
 974
 975static void i82092aa_module_exit(void)
 976{
 977        enter("i82092aa_module_exit");
 978        pci_unregister_driver(&i82092aa_pci_drv);
 979        unregister_ss_entry(&i82092aa_operations);
 980        if (sockets[0].io_base>0)
 981                         release_region(sockets[0].io_base, 2);
 982        leave("i82092aa_module_exit");
 983}
 984
 985module_init(i82092aa_module_init);
 986module_exit(i82092aa_module_exit);
 987
 988
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.