linux-old/drivers/pcmcia/pci_socket.c
<<
>>
Prefs
   1/*
   2 * Generic PCI pccard driver interface.
   3 *
   4 * (C) Copyright 1999 Linus Torvalds
   5 *
   6 * This implements the common parts of PCI pccard drivers,
   7 * notably detection and infrastructure conversion (ie change
   8 * from socket index to "struct pci_dev" etc)
   9 *
  10 * This does NOT implement the actual low-level driver details,
  11 * and this has on purpose been left generic enough that it can
  12 * be used to set up a PCI PCMCIA controller (ie non-cardbus),
  13 * or to set up a controller.
  14 *
  15 * See for example the "yenta" driver for PCI cardbus controllers
  16 * conforming to the yenta cardbus specifications.
  17 */
  18#include <linux/module.h>
  19
  20#include <linux/init.h>
  21#include <linux/pci.h>
  22#include <linux/sched.h>
  23#include <linux/interrupt.h>
  24
  25#include <pcmcia/ss.h>
  26
  27#include <asm/io.h>
  28
  29#include "pci_socket.h"
  30
  31
  32extern struct socket_info_t *pcmcia_register_socket (int slot,
  33                struct pccard_operations *vtable, int use_bus_pm);
  34extern void pcmcia_unregister_socket (struct socket_info_t *socket);
  35extern void pcmcia_suspend_socket (struct socket_info_t *socket);
  36extern void pcmcia_resume_socket (struct socket_info_t *socket);
  37
  38
  39/*
  40 * Arbitrary define. This is the array of active cardbus
  41 * entries.
  42 */
  43#define MAX_SOCKETS (8)
  44static pci_socket_t pci_socket_array[MAX_SOCKETS];
  45
  46static int pci_init_socket(unsigned int sock)
  47{
  48        pci_socket_t *socket = pci_socket_array + sock;
  49
  50        if (socket->op && socket->op->init)
  51                return socket->op->init(socket);
  52        return -EINVAL;
  53}
  54
  55static int pci_suspend_socket(unsigned int sock)
  56{
  57        pci_socket_t *socket = pci_socket_array + sock;
  58
  59        if (socket->op && socket->op->suspend)
  60                return socket->op->suspend(socket);
  61        return -EINVAL;
  62}
  63
  64static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
  65{
  66        pci_socket_t *socket = pci_socket_array + sock;
  67
  68        socket->handler = handler;
  69        socket->info = info;
  70        if (handler)
  71                MOD_INC_USE_COUNT;
  72        else
  73                MOD_DEC_USE_COUNT;
  74        return 0;
  75}
  76
  77static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
  78{
  79        pci_socket_t *socket = pci_socket_array + sock;
  80
  81        *cap = socket->cap;
  82        return 0;
  83}
  84
  85static int pci_get_status(unsigned int sock, unsigned int *value)
  86{
  87        pci_socket_t *socket = pci_socket_array + sock;
  88
  89        if (socket->op && socket->op->get_status)
  90                return socket->op->get_status(socket, value);
  91        *value = 0;
  92        return -EINVAL;
  93}
  94
  95static int pci_get_socket(unsigned int sock, socket_state_t *state)
  96{
  97        pci_socket_t *socket = pci_socket_array + sock;
  98
  99        if (socket->op && socket->op->get_socket)
 100                return socket->op->get_socket(socket, state);
 101        return -EINVAL;
 102}
 103
 104static int pci_set_socket(unsigned int sock, socket_state_t *state)
 105{
 106        pci_socket_t *socket = pci_socket_array + sock;
 107
 108        if (socket->op && socket->op->set_socket)
 109                return socket->op->set_socket(socket, state);
 110        return -EINVAL;
 111}
 112
 113static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io)
 114{
 115        pci_socket_t *socket = pci_socket_array + sock;
 116
 117        if (socket->op && socket->op->get_io_map)
 118                return socket->op->get_io_map(socket, io);
 119        return -EINVAL;
 120}
 121
 122static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
 123{
 124        pci_socket_t *socket = pci_socket_array + sock;
 125
 126        if (socket->op && socket->op->set_io_map)
 127                return socket->op->set_io_map(socket, io);
 128        return -EINVAL;
 129}
 130
 131static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
 132{
 133        pci_socket_t *socket = pci_socket_array + sock;
 134
 135        if (socket->op && socket->op->get_mem_map)
 136                return socket->op->get_mem_map(socket, mem);
 137        return -EINVAL;
 138}
 139
 140static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
 141{
 142        pci_socket_t *socket = pci_socket_array + sock;
 143
 144        if (socket->op && socket->op->set_mem_map)
 145                return socket->op->set_mem_map(socket, mem);
 146        return -EINVAL;
 147}
 148
 149static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
 150{
 151        pci_socket_t *socket = pci_socket_array + sock;
 152
 153        if (socket->op && socket->op->proc_setup)
 154                socket->op->proc_setup(socket, base);
 155}
 156
 157static struct pccard_operations pci_socket_operations = {
 158        pci_init_socket,
 159        pci_suspend_socket,
 160        pci_register_callback,
 161        pci_inquire_socket,
 162        pci_get_status,
 163        pci_get_socket,
 164        pci_set_socket,
 165        pci_get_io_map,
 166        pci_set_io_map,
 167        pci_get_mem_map,
 168        pci_set_mem_map,
 169        pci_proc_setup
 170};
 171
 172static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
 173{
 174        pci_socket_t *socket = nr + pci_socket_array;
 175        int err;
 176        
 177        memset(socket, 0, sizeof(*socket));
 178        socket->dev = dev;
 179        socket->op = ops;
 180        pci_set_drvdata(dev, socket);
 181        spin_lock_init(&socket->event_lock);
 182        err = socket->op->open(socket);
 183        if(err)
 184        {
 185                socket->dev = NULL;
 186                pci_set_drvdata(dev, NULL);
 187        }
 188        return err;
 189}
 190
 191void cardbus_register(pci_socket_t *socket)
 192{
 193        int nr = socket - pci_socket_array;
 194
 195        socket->pcmcia_socket = pcmcia_register_socket(nr, &pci_socket_operations, 1);
 196}
 197
 198static int __devinit
 199cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
 200{
 201        int     s;
 202
 203        for (s = 0; s < MAX_SOCKETS; s++) {
 204                if (pci_socket_array [s].dev == 0) {
 205                        return add_pci_socket (s, dev, &yenta_operations);
 206                }
 207        }
 208        return -ENODEV;
 209}
 210
 211static void __devexit cardbus_remove (struct pci_dev *dev)
 212{
 213        pci_socket_t *socket = pci_get_drvdata(dev);
 214
 215        pcmcia_unregister_socket (socket->pcmcia_socket);
 216        if (socket->op && socket->op->close)
 217                socket->op->close(socket);
 218        pci_set_drvdata(dev, NULL);
 219}
 220
 221static int cardbus_suspend (struct pci_dev *dev, u32 state)
 222{
 223        pci_socket_t *socket = pci_get_drvdata(dev);
 224        pcmcia_suspend_socket (socket->pcmcia_socket);
 225        return 0;
 226}
 227
 228static int cardbus_resume (struct pci_dev *dev)
 229{
 230        pci_socket_t *socket = pci_get_drvdata(dev);
 231        pcmcia_resume_socket (socket->pcmcia_socket);
 232        return 0;
 233}
 234
 235
 236static struct pci_device_id cardbus_table [] __devinitdata = { {
 237        class:          PCI_CLASS_BRIDGE_CARDBUS << 8,
 238        class_mask:     ~0,
 239
 240        vendor:         PCI_ANY_ID,
 241        device:         PCI_ANY_ID,
 242        subvendor:      PCI_ANY_ID,
 243        subdevice:      PCI_ANY_ID,
 244}, { /* all zeroes */ }
 245};
 246MODULE_DEVICE_TABLE(pci, cardbus_table);
 247
 248static struct pci_driver pci_cardbus_driver = {
 249        name:           "cardbus",
 250        id_table:       cardbus_table,
 251        probe:          cardbus_probe,
 252        remove:         __devexit_p(cardbus_remove),
 253        suspend:        cardbus_suspend,
 254        resume:         cardbus_resume,
 255};
 256
 257static int __init pci_socket_init(void)
 258{
 259        return pci_module_init (&pci_cardbus_driver);
 260}
 261
 262static void __exit pci_socket_exit (void)
 263{
 264        pci_unregister_driver (&pci_cardbus_driver);
 265}
 266
 267module_init(pci_socket_init);
 268module_exit(pci_socket_exit);
 269
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.