pci_socket.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
- /*
- * Generic PCI pccard driver interface.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * This implements the common parts of PCI pccard drivers,
- * notably detection and infrastructure conversion (ie change
- * from socket index to "struct pci_dev" etc)
- *
- * This does NOT implement the actual low-level driver details,
- * and this has on purpose been left generic enough that it can
- * be used to set up a PCI PCMCIA controller (ie non-cardbus),
- * or to set up a controller.
- *
- * See for example the "yenta" driver for PCI cardbus controllers
- * conforming to the yenta cardbus specifications.
- */
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/pci.h>
- #include <linux/sched.h>
- #include <linux/interrupt.h>
- #include <pcmcia/ss.h>
- #include <asm/io.h>
- #include "pci_socket.h"
- extern struct socket_info_t *pcmcia_register_socket (int slot,
- struct pccard_operations *vtable, int use_bus_pm);
- extern void pcmcia_unregister_socket (struct socket_info_t *socket);
- extern void pcmcia_suspend_socket (struct socket_info_t *socket);
- extern void pcmcia_resume_socket (struct socket_info_t *socket);
- /*
- * Arbitrary define. This is the array of active cardbus
- * entries.
- */
- #define MAX_SOCKETS (8)
- static pci_socket_t pci_socket_array[MAX_SOCKETS];
- static int pci_init_socket(unsigned int sock)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->init)
- return socket->op->init(socket);
- return -EINVAL;
- }
- static int pci_suspend_socket(unsigned int sock)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->suspend)
- return socket->op->suspend(socket);
- return -EINVAL;
- }
- static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- socket->handler = handler;
- socket->info = info;
- if (handler)
- MOD_INC_USE_COUNT;
- else
- MOD_DEC_USE_COUNT;
- return 0;
- }
- static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- *cap = socket->cap;
- return 0;
- }
- static int pci_get_status(unsigned int sock, unsigned int *value)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->get_status)
- return socket->op->get_status(socket, value);
- *value = 0;
- return -EINVAL;
- }
- static int pci_get_socket(unsigned int sock, socket_state_t *state)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->get_socket)
- return socket->op->get_socket(socket, state);
- return -EINVAL;
- }
- static int pci_set_socket(unsigned int sock, socket_state_t *state)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->set_socket)
- return socket->op->set_socket(socket, state);
- return -EINVAL;
- }
- static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->get_io_map)
- return socket->op->get_io_map(socket, io);
- return -EINVAL;
- }
- static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->set_io_map)
- return socket->op->set_io_map(socket, io);
- return -EINVAL;
- }
- static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->get_mem_map)
- return socket->op->get_mem_map(socket, mem);
- return -EINVAL;
- }
- static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->set_mem_map)
- return socket->op->set_mem_map(socket, mem);
- return -EINVAL;
- }
- static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
- {
- pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->proc_setup)
- socket->op->proc_setup(socket, base);
- }
- static struct pccard_operations pci_socket_operations = {
- pci_init_socket,
- pci_suspend_socket,
- pci_register_callback,
- pci_inquire_socket,
- pci_get_status,
- pci_get_socket,
- pci_set_socket,
- pci_get_io_map,
- pci_set_io_map,
- pci_get_mem_map,
- pci_set_mem_map,
- pci_proc_setup
- };
- static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
- {
- pci_socket_t *socket = nr + pci_socket_array;
- int err;
-
- memset(socket, 0, sizeof(*socket));
- socket->dev = dev;
- socket->op = ops;
- pci_set_drvdata(dev, socket);
- spin_lock_init(&socket->event_lock);
- err = socket->op->open(socket);
- if(err)
- {
- socket->dev = NULL;
- pci_set_drvdata(dev, NULL);
- }
- return err;
- }
- void cardbus_register(pci_socket_t *socket)
- {
- int nr = socket - pci_socket_array;
- socket->pcmcia_socket = pcmcia_register_socket(nr, &pci_socket_operations, 1);
- }
- static int __devinit
- cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
- {
- int s;
- for (s = 0; s < MAX_SOCKETS; s++) {
- if (pci_socket_array [s].dev == 0) {
- return add_pci_socket (s, dev, ¥ta_operations);
- }
- }
- return -ENODEV;
- }
- static void __devexit cardbus_remove (struct pci_dev *dev)
- {
- pci_socket_t *socket = pci_get_drvdata(dev);
- pcmcia_unregister_socket (socket->pcmcia_socket);
- if (socket->op && socket->op->close)
- socket->op->close(socket);
- pci_set_drvdata(dev, NULL);
- }
- static int cardbus_suspend (struct pci_dev *dev, u32 state)
- {
- pci_socket_t *socket = pci_get_drvdata(dev);
- pcmcia_suspend_socket (socket->pcmcia_socket);
- return 0;
- }
- static int cardbus_resume (struct pci_dev *dev)
- {
- pci_socket_t *socket = pci_get_drvdata(dev);
- pcmcia_resume_socket (socket->pcmcia_socket);
- return 0;
- }
- static struct pci_device_id cardbus_table [] __devinitdata = { {
- class: PCI_CLASS_BRIDGE_CARDBUS << 8,
- class_mask: ~0,
- vendor: PCI_ANY_ID,
- device: PCI_ANY_ID,
- subvendor: PCI_ANY_ID,
- subdevice: PCI_ANY_ID,
- }, { /* all zeroes */ }
- };
- MODULE_DEVICE_TABLE(pci, cardbus_table);
- static struct pci_driver pci_cardbus_driver = {
- name: "cardbus",
- id_table: cardbus_table,
- probe: cardbus_probe,
- remove: __devexit_p(cardbus_remove),
- suspend: cardbus_suspend,
- resume: cardbus_resume,
- };
- static int __init pci_socket_init(void)
- {
- return pci_module_init (&pci_cardbus_driver);
- }
- static void __exit pci_socket_exit (void)
- {
- pci_unregister_driver (&pci_cardbus_driver);
- }
- module_init(pci_socket_init);
- module_exit(pci_socket_exit);