diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 301eecf297434fc7d4ab8450e4c8818a23d9d851..d06cfa73d893201714b0becddc5b83fc9f02670a 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -29,8 +29,8 @@ config PCMCIA and ds. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. -config CARDBUS - bool "CardBus support" +config YENTA + tristate "CardBus yenta-compatible bridge support" depends on PCMCIA && PCI ---help--- CardBus is a bus mastering architecture for PC-cards, which allows @@ -48,6 +48,11 @@ config CARDBUS If unsure, say Y. +config CARDBUS + bool + depends on YENTA + default y if YENTA + config I82092 tristate "i82092 compatible bridge support" depends on PCMCIA && PCI @@ -58,7 +63,7 @@ config I82092 config I82365 tristate "i82365 compatible bridge support" - depends on PCMCIA + depends on PCMCIA && ISA help Say Y here to include support for ISA-bus PCMCIA host bridges that are register compatible with the Intel i82365. These are found on diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 32c8efc83192dc6132293839f5843b9f57738c12..6e83826cf74effd7d0811c5496f063c82c9ade9b 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -3,9 +3,7 @@ # obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o -ifeq ($(CONFIG_CARDBUS),y) - obj-$(CONFIG_PCMCIA) += yenta_socket.o -endif +obj-$(CONFIG_YENTA) += yenta.o obj-$(CONFIG_I82365) += i82365.o obj-$(CONFIG_I82092) += i82092.o @@ -14,8 +12,6 @@ obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o -yenta_socket-y += pci_socket.o yenta.o - pcmcia_core-y += cistpl.o rsrc_mgr.o bulkmem.o cs.o pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c index 4419780fb6d6ee874707c6a8da15372a5e96431d..01c843e44b0ac140a58fae07f6b67462041a665b 100644 --- a/drivers/pcmcia/bulkmem.c +++ b/drivers/pcmcia/bulkmem.c @@ -63,7 +63,7 @@ static int do_mtd_request(memory_handle_t handle, mtd_request_t *req, { int ret, tries; client_t *mtd; - socket_info_t *s; + struct pcmcia_socket *s; mtd = handle->mtd; if (mtd == NULL) @@ -130,7 +130,7 @@ static void retry_erase(erase_busy_t *busy, u_int cause) eraseq_entry_t *erase = busy->erase; mtd_request_t req; client_t *mtd; - socket_info_t *s; + struct pcmcia_socket *s; int ret; DEBUG(2, "cs: trying erase request 0x%p...\n", busy); @@ -259,27 +259,27 @@ static int mtd_modify_window(window_handle_t win, mtd_mod_win_t *req) win->ctl.flags |= MAP_ATTRIB; win->ctl.speed = req->AccessSpeed; win->ctl.card_start = req->CardOffset; - win->sock->ss_entry->set_mem_map(win->sock->sock, &win->ctl); + win->sock->ss_entry->set_mem_map(win->sock, &win->ctl); return CS_SUCCESS; } static int mtd_set_vpp(client_handle_t handle, mtd_vpp_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; if (req->Vpp1 != req->Vpp2) return CS_BAD_VPP; s = SOCKET(handle); s->socket.Vpp = req->Vpp1; - if (s->ss_entry->set_socket(s->sock, &s->socket)) + if (s->ss_entry->set_socket(s, &s->socket)) return CS_BAD_VPP; return CS_SUCCESS; } static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); @@ -287,7 +287,7 @@ static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req) s->socket.csc_mask |= SS_READY; else s->socket.csc_mask &= ~SS_READY; - if (s->ss_entry->set_socket(s->sock, &s->socket)) + if (s->ss_entry->set_socket(s, &s->socket)) return CS_GENERAL_FAILURE; return CS_SUCCESS; } @@ -417,7 +417,7 @@ static int match_region(client_handle_t handle, memory_handle_t list, int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn) { - socket_info_t *s = SOCKET(handle); + struct pcmcia_socket *s = SOCKET(handle); if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; @@ -450,7 +450,7 @@ int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn) int pcmcia_register_mtd(client_handle_t handle, mtd_reg_t *reg) { memory_handle_t list; - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; @@ -533,12 +533,12 @@ int pcmcia_check_erase_queue(eraseq_handle_t eraseq) int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open, memory_handle_t *mh) { - socket_info_t *s; + struct pcmcia_socket *s; memory_handle_t region; if ((handle == NULL) || CHECK_HANDLE(*handle)) return CS_BAD_HANDLE; - s = SOCKET(*handle); + s = (*handle)->Socket; if (open->Attributes & MEMORY_TYPE_AM) region = s->a_region; else diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index b10a31a7caa1f59d6cf5ae7c9bff5e05631054bd..b512673bd2acf2f19712c83612a89b01dea74813 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -119,11 +119,11 @@ static u_int xlate_rom_addr(u_char * b, u_int addr) These are similar to setup_cis_mem and release_cis_mem for 16-bit cards. The "result" that is used externally is the cb_cis_virt - pointer in the socket_info_t structure. + pointer in the struct pcmcia_socket structure. =====================================================================*/ -static void cb_release_cis_mem(socket_info_t * s) +static void cb_release_cis_mem(struct pcmcia_socket * s) { if (s->cb_cis_virt) { DEBUG(1, "cs: cb_release_cis_mem()\n"); @@ -133,7 +133,7 @@ static void cb_release_cis_mem(socket_info_t * s) } } -static int cb_setup_cis_mem(socket_info_t * s, struct resource *res) +static int cb_setup_cis_mem(struct pcmcia_socket * s, struct resource *res) { unsigned int start, size; @@ -162,7 +162,7 @@ static int cb_setup_cis_mem(socket_info_t * s, struct resource *res) =====================================================================*/ -int read_cb_mem(socket_info_t * s, int space, u_int addr, u_int len, void *ptr) +int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void *ptr) { struct pci_dev *dev; struct resource *res; @@ -237,7 +237,7 @@ static void cardbus_assign_irqs(struct pci_bus *bus, int irq) } } -int cb_alloc(socket_info_t * s) +int cb_alloc(struct pcmcia_socket * s) { struct pci_bus *bus = s->cap.cb_dev->subordinate; struct pci_dev *dev; @@ -266,7 +266,7 @@ int cb_alloc(socket_info_t * s) return CS_SUCCESS; } -void cb_free(socket_info_t * s) +void cb_free(struct pcmcia_socket * s) { struct pci_dev *bridge = s->cap.cb_dev; diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 303ee17d6825eac3ac480939cff071a83399194b..5d27f616dee4f83cbb95a536edab6839a0bb1627 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -82,11 +82,11 @@ static const u_int exponent[] = { INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */ -void release_cis_mem(socket_info_t *s) +void release_cis_mem(struct pcmcia_socket *s) { if (s->cis_mem.sys_start != 0) { s->cis_mem.flags &= ~MAP_ACTIVE; - s->ss_entry->set_mem_map(s->sock, &s->cis_mem); + s->ss_entry->set_mem_map(s, &s->cis_mem); if (!(s->cap.features & SS_CAP_STATIC_MAP)) release_mem_region(s->cis_mem.sys_start, s->cap.map_size); iounmap(s->cis_virt); @@ -101,7 +101,7 @@ void release_cis_mem(socket_info_t *s) * map the memory space. */ static unsigned char * -set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags) +set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) { pccard_mem_map *mem = &s->cis_mem; if (!(s->cap.features & SS_CAP_STATIC_MAP) && @@ -119,7 +119,7 @@ set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags) } mem->card_start = card_offset; mem->flags = flags; - s->ss_entry->set_mem_map(s->sock, mem); + s->ss_entry->set_mem_map(s, mem); if (s->cap.features & SS_CAP_STATIC_MAP) { if (s->cis_virt) iounmap(s->cis_virt); @@ -139,7 +139,7 @@ set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags) #define IS_ATTR 1 #define IS_INDIRECT 8 -int read_cis_mem(socket_info_t *s, int attr, u_int addr, +int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { u_char *sys, *end, *buf = ptr; @@ -202,7 +202,7 @@ int read_cis_mem(socket_info_t *s, int attr, u_int addr, return 0; } -void write_cis_mem(socket_info_t *s, int attr, u_int addr, +void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { u_char *sys, *end, *buf = ptr; @@ -266,7 +266,7 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr, ======================================================================*/ -static void read_cis_cache(socket_info_t *s, int attr, u_int addr, +static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { struct cis_cache_entry *cis; @@ -306,7 +306,7 @@ static void read_cis_cache(socket_info_t *s, int attr, u_int addr, } static void -remove_cis_cache(socket_info_t *s, int attr, u_int addr, u_int len) +remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len) { struct cis_cache_entry *cis; @@ -318,7 +318,7 @@ remove_cis_cache(socket_info_t *s, int attr, u_int addr, u_int len) } } -void destroy_cis_cache(socket_info_t *s) +void destroy_cis_cache(struct pcmcia_socket *s) { struct list_head *l, *n; @@ -337,7 +337,7 @@ void destroy_cis_cache(socket_info_t *s) ======================================================================*/ -int verify_cis_cache(socket_info_t *s) +int verify_cis_cache(struct pcmcia_socket *s) { struct cis_cache_entry *cis; char buf[256]; @@ -369,7 +369,7 @@ int verify_cis_cache(socket_info_t *s) int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis) { - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); @@ -409,7 +409,7 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple); int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) { - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); @@ -445,7 +445,7 @@ int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple) return pcmcia_get_next_tuple(handle, tuple); } -static int follow_link(socket_info_t *s, tuple_t *tuple) +static int follow_link(struct pcmcia_socket *s, tuple_t *tuple) { u_char link[5]; u_int ofs; @@ -487,7 +487,7 @@ static int follow_link(socket_info_t *s, tuple_t *tuple) int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) { - socket_info_t *s; + struct pcmcia_socket *s; u_char link[2], tmp; int ofs, i, attr; @@ -588,7 +588,7 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple) int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple) { - socket_info_t *s; + struct pcmcia_socket *s; u_int len; if (CHECK_HANDLE(handle)) diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index ba9a69e5c5e2a64c9f532ea680f9afae85d5eb31..be950332b5504c7f2f6c9c18f1921483415e3e7c 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -124,9 +124,11 @@ socket_state_t dead_socket = { 0, SS_DETECT, 0, 0, 0 }; -/* Table of sockets */ -socket_t sockets = 0; -socket_info_t *socket_table[MAX_SOCK]; + +/* List of all sockets, protected by a rwsem */ +LIST_HEAD(pcmcia_socket_list); +DECLARE_RWSEM(pcmcia_socket_list_rwsem); + #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_pccard = NULL; @@ -235,48 +237,48 @@ static const lookup_t service_table[] = { ======================================================================*/ -static int register_callback(socket_info_t *s, void (*handler)(void *, unsigned int), void * info) +static int register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info) { int error; if (handler && !try_module_get(s->ss_entry->owner)) return -ENODEV; - error = s->ss_entry->register_callback(s->sock, handler, info); + error = s->ss_entry->register_callback(s, handler, info); if (!handler) module_put(s->ss_entry->owner); return error; } -static int get_socket_status(socket_info_t *s, int *val) +static int get_socket_status(struct pcmcia_socket *s, int *val) { - return s->ss_entry->get_status(s->sock, val); + return s->ss_entry->get_status(s, val); } -static int set_socket(socket_info_t *s, socket_state_t *state) +static int set_socket(struct pcmcia_socket *s, socket_state_t *state) { - return s->ss_entry->set_socket(s->sock, state); + return s->ss_entry->set_socket(s, state); } -static int set_io_map(socket_info_t *s, struct pccard_io_map *io) +static int set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) { - return s->ss_entry->set_io_map(s->sock, io); + return s->ss_entry->set_io_map(s, io); } -static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem) +static int set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) { - return s->ss_entry->set_mem_map(s->sock, mem); + return s->ss_entry->set_mem_map(s, mem); } -static int suspend_socket(socket_info_t *s) +static int suspend_socket(struct pcmcia_socket *s) { s->socket = dead_socket; - return s->ss_entry->suspend(s->sock); + return s->ss_entry->suspend(s); } -static int init_socket(socket_info_t *s) +static int init_socket(struct pcmcia_socket *s) { s->socket = dead_socket; - return s->ss_entry->init(s->sock); + return s->ss_entry->init(s); } /*====================================================================*/ @@ -285,7 +287,7 @@ static int init_socket(socket_info_t *s) static int proc_read_clients(char *buf, char **start, off_t pos, int count, int *eof, void *data) { - socket_info_t *s = data; + struct pcmcia_socket *s = data; client_handle_t c; char *p = buf; @@ -303,145 +305,226 @@ static int proc_read_clients(char *buf, char **start, off_t pos, ======================================================================*/ -static int pccardd(void *__skt); -void pcmcia_unregister_socket(struct class_device *dev); +/** + * socket drivers are expected to use the following callbacks in their + * .drv struct: + * - pcmcia_socket_dev_suspend + * - pcmcia_socket_dev_resume + * These functions check for the appropriate struct pcmcia_soket arrays, + * and pass them to the low-level functions pcmcia_{suspend,resume}_socket + */ +static int socket_resume(struct pcmcia_socket *skt); +static int socket_suspend(struct pcmcia_socket *skt); + +int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level) +{ + struct pcmcia_socket *socket; + + if (level != SUSPEND_SAVE_STATE) + return 0; + + down_read(&pcmcia_socket_list_rwsem); + list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { + if (socket->dev.dev != dev) + continue; + down(&socket->skt_sem); + socket_suspend(socket); + up(&socket->skt_sem); + } + up_read(&pcmcia_socket_list_rwsem); + + return 0; +} +EXPORT_SYMBOL(pcmcia_socket_dev_suspend); + +int pcmcia_socket_dev_resume(struct device *dev, u32 level) +{ + struct pcmcia_socket *socket; + if (level != RESUME_RESTORE_STATE) + return 0; + + down_read(&pcmcia_socket_list_rwsem); + list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { + if (socket->dev.dev != dev) + continue; + down(&socket->skt_sem); + socket_resume(socket); + up(&socket->skt_sem); + } + up_read(&pcmcia_socket_list_rwsem); + + return 0; +} +EXPORT_SYMBOL(pcmcia_socket_dev_resume); + + +static int pccardd(void *__skt); #define to_class_data(dev) dev->class_data -/** - * pcmcia_register_socket - add a new pcmcia socket device - */ -int pcmcia_register_socket(struct class_device *class_dev) +static int pcmcia_add_socket(struct class_device *class_dev) { - struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev); - socket_info_t *s_info; - unsigned int i, j, ret; + struct pcmcia_socket *socket = class_get_devdata(class_dev); + int ret = 0; - if (!cls_d) - return -EINVAL; + /* base address = 0, map = 0 */ + socket->cis_mem.flags = 0; + socket->cis_mem.speed = cis_speed; + socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy; + INIT_LIST_HEAD(&socket->cis_cache); + spin_lock_init(&socket->lock); - DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", cls_d->ops); - - s_info = kmalloc(cls_d->nsock * sizeof(struct socket_info_t), GFP_KERNEL); - if (!s_info) - return -ENOMEM; - memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t)); - - cls_d->s_info = s_info; - ret = 0; - - /* socket initialization */ - for (i = 0; i < cls_d->nsock; i++) { - socket_info_t *s = &s_info[i]; - - s->ss_entry = cls_d->ops; - s->sock = i + cls_d->sock_offset; - - /* base address = 0, map = 0 */ - s->cis_mem.flags = 0; - s->cis_mem.speed = cis_speed; - s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; - INIT_LIST_HEAD(&s->cis_cache); - spin_lock_init(&s->lock); - - /* TBD: remove usage of socket_table, use class_for_each_dev instead */ - for (j = 0; j < sockets; j++) - if (socket_table[j] == NULL) break; - socket_table[j] = s; - if (j == sockets) sockets++; - - init_socket(s); - s->ss_entry->inquire_socket(s->sock, &s->cap); - - init_completion(&s->thread_done); - init_waitqueue_head(&s->thread_wait); - init_MUTEX(&s->skt_sem); - spin_lock_init(&s->thread_lock); - ret = kernel_thread(pccardd, s, CLONE_KERNEL); - if (ret < 0) { - pcmcia_unregister_socket(class_dev); - break; - } + init_socket(socket); + socket->ss_entry->inquire_socket(socket, &socket->cap); + + init_completion(&socket->thread_done); + init_waitqueue_head(&socket->thread_wait); + init_MUTEX(&socket->skt_sem); + spin_lock_init(&socket->thread_lock); + ret = kernel_thread(pccardd, socket, CLONE_KERNEL); + if (ret < 0) + return ret; - wait_for_completion(&s->thread_done); - BUG_ON(!s->thread); + wait_for_completion(&socket->thread_done); + BUG_ON(!socket->thread); #ifdef CONFIG_PROC_FS - if (proc_pccard) { - char name[3]; - sprintf(name, "%02d", j); - s->proc = proc_mkdir(name, proc_pccard); - if (s->proc) - s->ss_entry->proc_setup(i, s->proc); + if (proc_pccard) { + char name[3]; + sprintf(name, "%02d", socket->sock); + socket->proc = proc_mkdir(name, proc_pccard); + if (socket->proc) + socket->ss_entry->proc_setup(socket, socket->proc); #ifdef PCMCIA_DEBUG - if (s->proc) - create_proc_read_entry("clients", 0, s->proc, - proc_read_clients, s); + if (socket->proc) + create_proc_read_entry("clients", 0, socket->proc, + proc_read_clients, socket); #endif - } + } +#endif + return 0; +} + +static void pcmcia_remove_socket(struct class_device *class_dev) +{ + struct pcmcia_socket *socket = class_get_devdata(class_dev); + client_t *client; + +#ifdef CONFIG_PROC_FS + if (proc_pccard) { + char name[3]; + sprintf(name, "%02d", socket->sock); +#ifdef PCMCIA_DEBUG + remove_proc_entry("clients", socket->proc); #endif + remove_proc_entry(name, proc_pccard); } - return ret; +#endif + if (socket->thread) { + init_completion(&socket->thread_done); + socket->thread = NULL; + wake_up(&socket->thread_wait); + wait_for_completion(&socket->thread_done); + } + release_cis_mem(socket); + while (socket->clients) { + client = socket->clients; + socket->clients = socket->clients->next; + kfree(client); + } + socket->ss_entry = NULL; +} + + +/** + * pcmcia_register_socket - add a new pcmcia socket device + */ +int pcmcia_register_socket(struct pcmcia_socket *socket) +{ + if (!socket || !socket->ss_entry || !socket->dev.dev) + return -EINVAL; + + DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", socket->ss_entry); + + /* try to obtain a socket number [yes, it gets ugly if we + * register more than 2^sizeof(unsigned int) pcmcia + * sockets... but the socket number is deprecated + * anyways, so I don't care] */ + down_write(&pcmcia_socket_list_rwsem); + if (list_empty(&pcmcia_socket_list)) + socket->sock = 0; + else { + unsigned int found, i = 1; + struct pcmcia_socket *tmp; + do { + found = 1; + list_for_each_entry(tmp, &pcmcia_socket_list, socket_list) { + if (tmp->sock == i) + found = 0; + } + i++; + } while (!found); + socket->sock = i - 1; + } + list_add_tail(&socket->socket_list, &pcmcia_socket_list); + up_write(&pcmcia_socket_list_rwsem); + + + /* set proper values in socket->dev */ + socket->dev.class_data = socket; + socket->dev.class = &pcmcia_socket_class; + snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u\n", socket->sock); + + /* register with the device core */ + if (class_device_register(&socket->dev)) { + down_write(&pcmcia_socket_list_rwsem); + list_del(&socket->socket_list); + up_write(&pcmcia_socket_list_rwsem); + return -EINVAL; + } + + return 0; } /* pcmcia_register_socket */ +EXPORT_SYMBOL(pcmcia_register_socket); /** * pcmcia_unregister_socket - remove a pcmcia socket device */ -void pcmcia_unregister_socket(struct class_device *class_dev) +void pcmcia_unregister_socket(struct pcmcia_socket *socket) { - struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev); - unsigned int i; - int j, socket = -1; - client_t *client; - socket_info_t *s; - - if (!cls_d) + if (!socket) return; - s = (socket_info_t *) cls_d->s_info; + DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ss_entry); - for (i = 0; i < cls_d->nsock; i++) { - for (j = 0; j < MAX_SOCK; j++) - if (socket_table [j] == s) { - socket = j; - break; - } - if (socket < 0) - continue; - -#ifdef CONFIG_PROC_FS - if (proc_pccard) { - char name[3]; - sprintf(name, "%02d", socket); -#ifdef PCMCIA_DEBUG - remove_proc_entry("clients", s->proc); -#endif - remove_proc_entry(name, proc_pccard); - } -#endif - if (s->thread) { - init_completion(&s->thread_done); - s->thread = NULL; - wake_up(&s->thread_wait); - wait_for_completion(&s->thread_done); - } - release_cis_mem(s); - while (s->clients) { - client = s->clients; - s->clients = s->clients->next; - kfree(client); - } - s->ss_entry = NULL; - socket_table[socket] = NULL; - for (j = socket; j < sockets-1; j++) - socket_table[j] = socket_table[j+1]; - sockets--; + /* remove from the device core */ + class_device_unregister(&socket->dev); - s++; - } - kfree(cls_d->s_info); + /* remove from our own list */ + down_write(&pcmcia_socket_list_rwsem); + list_del(&socket->socket_list); + up_write(&pcmcia_socket_list_rwsem); } /* pcmcia_unregister_socket */ +EXPORT_SYMBOL(pcmcia_unregister_socket); + + +struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr) +{ + struct pcmcia_socket *s; + + down_read(&pcmcia_socket_list_rwsem); + list_for_each_entry(s, &pcmcia_socket_list, socket_list) + if (s->sock == nr) { + up_read(&pcmcia_socket_list_rwsem); + return s; + } + up_read(&pcmcia_socket_list_rwsem); + + return NULL; + +} +EXPORT_SYMBOL(pcmcia_get_socket_by_nr); /*====================================================================== @@ -465,9 +548,9 @@ static void free_regions(memory_handle_t *list) } } -static int send_event(socket_info_t *s, event_t event, int priority); +static int send_event(struct pcmcia_socket *s, event_t event, int priority); -static void shutdown_socket(socket_info_t *s) +static void shutdown_socket(struct pcmcia_socket *s) { client_t **c; @@ -522,7 +605,7 @@ static void shutdown_socket(socket_info_t *s) ======================================================================*/ -static int send_event(socket_info_t *s, event_t event, int priority) +static int send_event(struct pcmcia_socket *s, event_t event, int priority) { client_t *client = s->clients; int ret; @@ -543,7 +626,7 @@ static int send_event(socket_info_t *s, event_t event, int priority) return ret; } /* send_event */ -static void pcmcia_error(socket_info_t *skt, const char *fmt, ...) +static void pcmcia_error(struct pcmcia_socket *skt, const char *fmt, ...) { static char buf[128]; va_list ap; @@ -559,7 +642,7 @@ static void pcmcia_error(socket_info_t *skt, const char *fmt, ...) #define cs_to_timeout(cs) (((cs) * HZ + 99) / 100) -static void socket_remove_drivers(socket_info_t *skt) +static void socket_remove_drivers(struct pcmcia_socket *skt) { client_t *client; @@ -570,7 +653,7 @@ static void socket_remove_drivers(socket_info_t *skt) client->state |= CLIENT_STALE; } -static void socket_shutdown(socket_info_t *skt) +static void socket_shutdown(struct pcmcia_socket *skt) { socket_remove_drivers(skt); set_current_state(TASK_UNINTERRUPTIBLE); @@ -579,7 +662,7 @@ static void socket_shutdown(socket_info_t *skt) shutdown_socket(skt); } -static int socket_reset(socket_info_t *skt) +static int socket_reset(struct pcmcia_socket *skt) { int status, i; @@ -609,7 +692,7 @@ static int socket_reset(socket_info_t *skt) return CS_GENERAL_FAILURE; } -static int socket_setup(socket_info_t *skt, int initial_delay) +static int socket_setup(struct pcmcia_socket *skt, int initial_delay) { int status, i; @@ -673,7 +756,7 @@ static int socket_setup(socket_info_t *skt, int initial_delay) * Handle card insertion. Setup the socket, reset the card, * and then tell the rest of PCMCIA that a card is present. */ -static int socket_insert(socket_info_t *skt) +static int socket_insert(struct pcmcia_socket *skt) { int ret; @@ -693,7 +776,7 @@ static int socket_insert(socket_info_t *skt) return ret; } -static int socket_suspend(socket_info_t *skt) +static int socket_suspend(struct pcmcia_socket *skt) { if (skt->state & SOCKET_SUSPEND) return CS_IN_USE; @@ -710,7 +793,7 @@ static int socket_suspend(socket_info_t *skt) * our cached copy. If they are different, the card has been * replaced, and we need to tell the drivers. */ -static int socket_resume(socket_info_t *skt) +static int socket_resume(struct pcmcia_socket *skt) { int ret; @@ -742,7 +825,7 @@ static int socket_resume(socket_info_t *skt) static int pccardd(void *__skt) { - socket_info_t *skt = __skt; + struct pcmcia_socket *skt = __skt; DECLARE_WAITQUEUE(wait, current); daemonize("pccardd"); @@ -799,7 +882,7 @@ static int pccardd(void *__skt) static void parse_events(void *info, u_int events) { - socket_info_t *s = info; + struct pcmcia_socket *s = info; spin_lock(&s->thread_lock); s->thread_events |= events; @@ -808,68 +891,6 @@ static void parse_events(void *info, u_int events) wake_up(&s->thread_wait); } /* parse_events */ -/*====================================================================== - - Another event handler, for power management events. - - This does not comply with the latest PC Card spec for handling - power management events. - -======================================================================*/ - -void pcmcia_suspend_socket (socket_info_t *skt) -{ - down(&skt->skt_sem); - socket_suspend(skt); - up(&skt->skt_sem); -} - -void pcmcia_resume_socket (socket_info_t *skt) -{ - down(&skt->skt_sem); - socket_resume(skt); - up(&skt->skt_sem); -} - - -int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level) -{ - socket_info_t *s; - int i; - - if ((!cls_d) || (level != SUSPEND_SAVE_STATE)) - return 0; - - s = (socket_info_t *) cls_d->s_info; - - for (i = 0; i < cls_d->nsock; i++) { - pcmcia_suspend_socket(s); - s++; - } - - return 0; -} -EXPORT_SYMBOL(pcmcia_socket_dev_suspend); - -int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level) -{ - socket_info_t *s; - int i; - - if ((!cls_d) || (level != RESUME_RESTORE_STATE)) - return 0; - - s = (socket_info_t *) cls_d->s_info; - - for (i = 0; i < cls_d->nsock; i++) { - pcmcia_resume_socket(s); - s++; - } - - return 0; -} -EXPORT_SYMBOL(pcmcia_socket_dev_resume); - /*====================================================================== @@ -877,7 +898,7 @@ EXPORT_SYMBOL(pcmcia_socket_dev_resume); ======================================================================*/ -static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base, +static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, ioaddr_t num, u_int lines, char *name) { int i; @@ -941,7 +962,7 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base, return (i == MAX_IO_WIN); } /* alloc_io_space */ -static void release_io_space(socket_info_t *s, ioaddr_t base, +static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num) { int i; @@ -969,7 +990,7 @@ static void release_io_space(socket_info_t *s, ioaddr_t base, int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg) { - socket_info_t *s; + struct pcmcia_socket *s; config_t *c; int addr; u_char val; @@ -1020,18 +1041,18 @@ int pcmcia_access_configuration_register(client_handle_t handle, int pcmcia_bind_device(bind_req_t *req) { client_t *client; - socket_info_t *s; + struct pcmcia_socket *s; - if (CHECK_SOCKET(req->Socket)) - return CS_BAD_SOCKET; - s = SOCKET(req); + s = req->Socket; + if (!s) + return CS_BAD_SOCKET; client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL); if (!client) return CS_OUT_OF_RESOURCE; memset(client, '\0', sizeof(client_t)); client->client_magic = CLIENT_MAGIC; strlcpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN); - client->Socket = req->Socket; + client->Socket = s; client->Function = req->Function; client->state = CLIENT_UNBOUND; client->erase_busy.next = &client->erase_busy; @@ -1055,12 +1076,12 @@ int pcmcia_bind_device(bind_req_t *req) int pcmcia_bind_mtd(mtd_bind_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; memory_handle_t region; - if (CHECK_SOCKET(req->Socket)) - return CS_BAD_SOCKET; - s = SOCKET(req); + s = req->Socket; + if (!s) + return CS_BAD_SOCKET; if (req->Attributes & REGION_TYPE_AM) region = s->a_region; @@ -1085,10 +1106,10 @@ int pcmcia_bind_mtd(mtd_bind_t *req) int pcmcia_deregister_client(client_handle_t handle) { client_t **client; - socket_info_t *s; + struct pcmcia_socket *s; memory_handle_t region; u_long flags; - int i, sn; + int i; DEBUG(1, "cs: deregister_client(%p)\n", handle); if (CHECK_HANDLE(handle)) @@ -1109,8 +1130,6 @@ int pcmcia_deregister_client(client_handle_t handle) if (region->mtd == handle) region->mtd = NULL; } - sn = handle->Socket; s = socket_table[sn]; - if ((handle->state & CLIENT_STALE) || (handle->Attributes & INFO_MASTER_CLIENT)) { spin_lock_irqsave(&s->lock, flags); @@ -1142,7 +1161,7 @@ int pcmcia_deregister_client(client_handle_t handle) int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config) { - socket_info_t *s; + struct pcmcia_socket *s; config_t *c; if (CHECK_HANDLE(handle)) @@ -1212,9 +1231,15 @@ int pcmcia_get_configuration_info(client_handle_t handle, int pcmcia_get_card_services_info(servinfo_t *info) { + unsigned int socket_count = 0; + struct list_head *tmp; info->Signature[0] = 'C'; info->Signature[1] = 'S'; - info->Count = sockets; + down_read(&pcmcia_socket_list_rwsem); + list_for_each(tmp, &pcmcia_socket_list) + socket_count++; + up_read(&pcmcia_socket_list_rwsem); + info->Count = socket_count; info->Revision = CS_RELEASE_CODE; info->CSLevel = 0x0210; info->VendorString = (char *)release; @@ -1231,15 +1256,17 @@ int pcmcia_get_card_services_info(servinfo_t *info) int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req) { socket_t s; + struct pcmcia_socket *socket; if (req->Attributes & CLIENT_THIS_SOCKET) s = req->Socket; else s = 0; - if (CHECK_SOCKET(req->Socket)) + socket = pcmcia_get_socket_by_nr(s); + if (!socket) return CS_BAD_SOCKET; - if (socket_table[s]->clients == NULL) + if (socket->clients == NULL) return CS_NO_MORE_ITEMS; - *handle = socket_table[s]->clients; + *handle = socket->clients; return CS_SUCCESS; } /* get_first_client */ @@ -1247,13 +1274,13 @@ int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req) int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; if ((handle == NULL) || CHECK_HANDLE(*handle)) return CS_BAD_HANDLE; if ((*handle)->next == NULL) { if (req->Attributes & CLIENT_THIS_SOCKET) return CS_NO_MORE_ITEMS; - s = SOCKET(*handle); + s = (*handle)->Socket; if (s->clients == NULL) return CS_NO_MORE_ITEMS; *handle = s->clients; @@ -1266,12 +1293,12 @@ int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req) int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; window_t *win; int w; if (idx == 0) - s = SOCKET((client_handle_t)*handle); + s = ((client_handle_t)*handle)->Socket; else s = (*handle)->sock; if (!(s->state & SOCKET_PRESENT)) @@ -1321,7 +1348,7 @@ int pcmcia_get_next_window(window_handle_t *win, win_req_t *req) struct pci_bus *pcmcia_lookup_bus(client_handle_t handle) { - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle)) return NULL; @@ -1345,7 +1372,7 @@ EXPORT_SYMBOL(pcmcia_lookup_bus); int pcmcia_get_status(client_handle_t handle, cs_status_t *status) { - socket_info_t *s; + struct pcmcia_socket *s; config_t *c; int val; @@ -1424,7 +1451,7 @@ int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; if (req->Page != 0) @@ -1445,7 +1472,7 @@ int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) int pcmcia_modify_configuration(client_handle_t handle, modconf_t *mod) { - socket_info_t *s; + struct pcmcia_socket *s; config_t *c; if (CHECK_HANDLE(handle)) @@ -1522,14 +1549,13 @@ int pcmcia_modify_window(window_handle_t win, modwin_t *req) int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) { - client_t *client; - socket_info_t *s; - socket_t ns; + client_t *client = NULL; + struct pcmcia_socket *s; /* Look for unbound client with matching dev_info */ - client = NULL; - for (ns = 0; ns < sockets; ns++) { - client = socket_table[ns]->clients; + down_read(&pcmcia_socket_list_rwsem); + list_for_each_entry(s, &pcmcia_socket_list, socket_list) { + client = s->clients; while (client != NULL) { if ((strcmp(client->dev_info, (char *)req->dev_info) == 0) && (client->state & CLIENT_UNBOUND)) break; @@ -1537,10 +1563,10 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) } if (client != NULL) break; } + up_read(&pcmcia_socket_list_rwsem); if (client == NULL) return CS_OUT_OF_RESOURCE; - s = socket_table[ns]; if (++s->real_clients == 1) { register_callback(s, &parse_events, s); parse_events(s, SS_DETECT); @@ -1548,7 +1574,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) *handle = client; client->state &= ~CLIENT_UNBOUND; - client->Socket = ns; + client->Socket = s; client->Attributes = req->Attributes; client->EventMask = req->EventMask; client->event_handler = req->event_handler; @@ -1577,8 +1603,8 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) client, client->Socket, client->dev_info); if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE) EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW); - if ((socket_table[ns]->state & SOCKET_PRESENT) && - !(socket_table[ns]->state & SOCKET_SETUP_PENDING)) { + if ((s->state & SOCKET_PRESENT) && + !(s->state & SOCKET_SETUP_PENDING)) { if (client->EventMask & CS_EVENT_CARD_INSERTION) EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); else @@ -1592,7 +1618,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) int pcmcia_release_configuration(client_handle_t handle) { pccard_io_map io = { 0, 0, 0, 0, 1 }; - socket_info_t *s; + struct pcmcia_socket *s; int i; if (CHECK_HANDLE(handle) || @@ -1642,7 +1668,7 @@ int pcmcia_release_configuration(client_handle_t handle) int pcmcia_release_io(client_handle_t handle, io_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ)) return CS_BAD_HANDLE; @@ -1677,7 +1703,7 @@ int pcmcia_release_io(client_handle_t handle, io_req_t *req) int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ)) return CS_BAD_HANDLE; handle->state &= ~CLIENT_IRQ_REQ; @@ -1713,7 +1739,7 @@ int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) int pcmcia_release_window(window_handle_t win) { - socket_info_t *s; + struct pcmcia_socket *s; if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; @@ -1743,13 +1769,13 @@ int pcmcia_request_configuration(client_handle_t handle, { int i; u_int base; - socket_info_t *s; + struct pcmcia_socket *s; config_t *c; pccard_io_map iomap; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; - i = handle->Socket; s = socket_table[i]; + s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; @@ -1872,7 +1898,7 @@ int pcmcia_request_configuration(client_handle_t handle, int pcmcia_request_io(client_handle_t handle, io_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; config_t *c; if (CHECK_HANDLE(handle)) @@ -1936,7 +1962,7 @@ int pcmcia_request_io(client_handle_t handle, io_req_t *req) int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) { - socket_info_t *s; + struct pcmcia_socket *s; config_t *c; int ret = 0, irq = 0; @@ -2011,14 +2037,14 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh) { - socket_info_t *s; + struct pcmcia_socket *s; window_t *win; u_long align; int w; if (CHECK_HANDLE(*handle)) return CS_BAD_HANDLE; - s = SOCKET(*handle); + s = (*handle)->Socket; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (req->Attributes & (WIN_PAGED | WIN_SHARED)) @@ -2096,7 +2122,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle int pcmcia_reset_card(client_handle_t handle, client_req_t *req) { - socket_info_t *skt; + struct pcmcia_socket *skt; int ret; if (CHECK_HANDLE(handle)) @@ -2145,7 +2171,7 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req) int pcmcia_suspend_card(client_handle_t handle, client_req_t *req) { - socket_info_t *skt; + struct pcmcia_socket *skt; int ret; if (CHECK_HANDLE(handle)) @@ -2172,7 +2198,7 @@ int pcmcia_suspend_card(client_handle_t handle, client_req_t *req) int pcmcia_resume_card(client_handle_t handle, client_req_t *req) { - socket_info_t *skt; + struct pcmcia_socket *skt; int ret; if (CHECK_HANDLE(handle)) @@ -2205,7 +2231,7 @@ int pcmcia_resume_card(client_handle_t handle, client_req_t *req) int pcmcia_eject_card(client_handle_t handle, client_req_t *req) { - socket_info_t *skt; + struct pcmcia_socket *skt; int ret; if (CHECK_HANDLE(handle)) @@ -2234,7 +2260,7 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req) int pcmcia_insert_card(client_handle_t handle, client_req_t *req) { - socket_info_t *skt; + struct pcmcia_socket *skt; int ret; if (CHECK_HANDLE(handle)) @@ -2519,11 +2545,6 @@ EXPORT_SYMBOL(MTDHelperEntry); EXPORT_SYMBOL(proc_pccard); #endif -EXPORT_SYMBOL(pcmcia_register_socket); -EXPORT_SYMBOL(pcmcia_unregister_socket); -EXPORT_SYMBOL(pcmcia_suspend_socket); -EXPORT_SYMBOL(pcmcia_resume_socket); - struct class pcmcia_socket_class = { .name = "pcmcia_socket", }; @@ -2531,8 +2552,8 @@ EXPORT_SYMBOL(pcmcia_socket_class); static struct class_interface pcmcia_socket = { .class = &pcmcia_socket_class, - .add = &pcmcia_register_socket, - .remove = &pcmcia_unregister_socket, + .add = &pcmcia_add_socket, + .remove = &pcmcia_remove_socket, }; diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index ffe7980fe1617cdf76ec03ade8d359087cd96a36..11c50e4a6049e4a8ad4a4ef9d7e513af24c062d2 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -21,13 +21,6 @@ #include <linux/config.h> -typedef struct erase_busy_t { - eraseq_entry_t *erase; - client_handle_t client; - struct timer_list timeout; - struct erase_busy_t *prev, *next; -} erase_busy_t; - #define ERASEQ_MAGIC 0xFA67 typedef struct eraseq_t { u_short eraseq_magic; @@ -39,7 +32,7 @@ typedef struct eraseq_t { #define CLIENT_MAGIC 0x51E6 typedef struct client_t { u_short client_magic; - socket_t Socket; + struct pcmcia_socket *Socket; u_char Function; dev_info_t dev_info; u_int Attributes; @@ -63,23 +56,6 @@ typedef struct client_t { #define CLIENT_WIN_REQ(i) (0x20<<(i)) #define CLIENT_CARDBUS 0x8000 -typedef struct io_window_t { - u_int Attributes; - ioaddr_t BasePort, NumPorts; - ioaddr_t InUse, Config; -} io_window_t; - -#define WINDOW_MAGIC 0xB35C -typedef struct window_t { - u_short magic; - u_short index; - client_handle_t handle; - struct socket_info_t *sock; - u_long base; - u_long size; - pccard_mem_map ctl; -} window_t; - #define REGION_MAGIC 0xE3C9 typedef struct region_t { u_short region_magic; @@ -108,12 +84,6 @@ typedef struct config_t { } irq; } config_t; -/* Maximum number of IO windows per socket */ -#define MAX_IO_WIN 2 - -/* Maximum number of memory windows per socket */ -#define MAX_WIN 4 - struct cis_cache_entry { struct list_head node; unsigned int addr; @@ -122,48 +92,6 @@ struct cis_cache_entry { unsigned char cache[0]; }; -typedef struct socket_info_t { - spinlock_t lock; - struct pccard_operations * ss_entry; - u_int sock; - socket_state_t socket; - socket_cap_t cap; - u_int state; - u_short functions; - u_short lock_count; - client_handle_t clients; - u_int real_clients; - pccard_mem_map cis_mem; - u_char *cis_virt; - config_t *config; -#ifdef CONFIG_CARDBUS - struct resource * cb_cis_res; - u_char *cb_cis_virt; -#endif - struct { - u_int AssignedIRQ; - u_int Config; - } irq; - io_window_t io[MAX_IO_WIN]; - window_t win[MAX_WIN]; - region_t *c_region, *a_region; - erase_busy_t erase_busy; - struct list_head cis_cache; - u_int fake_cis_len; - char *fake_cis; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc; -#endif - - struct semaphore skt_sem; /* protects socket h/w state */ - - struct task_struct *thread; - struct completion thread_done; - wait_queue_head_t thread_wait; - spinlock_t thread_lock; /* protects thread_events */ - unsigned int thread_events; -} socket_info_t; - /* Flags in config state */ #define CONFIG_LOCKED 0x01 #define CONFIG_IRQ_REQ 0x02 @@ -187,7 +115,7 @@ typedef struct socket_info_t { #define CHECK_SOCKET(s) \ (((s) >= sockets) || (socket_table[s]->ss_entry == NULL)) -#define SOCKET(h) (socket_table[(h)->Socket]) +#define SOCKET(h) (h->Socket) #define CONFIG(h) (&SOCKET(h)->config[(h)->Function]) #define CHECK_REGION(r) \ @@ -200,19 +128,19 @@ typedef struct socket_info_t { ((h)->event_handler((e), (p), &(h)->event_callback_args)) /* In cardbus.c */ -int cb_alloc(socket_info_t *s); -void cb_free(socket_info_t *s); -int read_cb_mem(socket_info_t *s, int space, u_int addr, u_int len, void *ptr); +int cb_alloc(struct pcmcia_socket *s); +void cb_free(struct pcmcia_socket *s); +int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr); /* In cistpl.c */ -int read_cis_mem(socket_info_t *s, int attr, +int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr); -void write_cis_mem(socket_info_t *s, int attr, +void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr); -void release_cis_mem(socket_info_t *s); -void destroy_cis_cache(socket_info_t *s); -int verify_cis_cache(socket_info_t *s); -void preload_cis_cache(socket_info_t *s); +void release_cis_mem(struct pcmcia_socket *s); +void destroy_cis_cache(struct pcmcia_socket *s); +int verify_cis_cache(struct pcmcia_socket *s); +void preload_cis_cache(struct pcmcia_socket *s); int get_first_tuple(client_handle_t handle, tuple_t *tuple); int get_next_tuple(client_handle_t handle, tuple_t *tuple); int get_tuple_data(client_handle_t handle, tuple_t *tuple); @@ -236,11 +164,11 @@ int write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf); int copy_memory(memory_handle_t handle, copy_op_t *req); /* In rsrc_mgr */ -void validate_mem(socket_info_t *s); +void validate_mem(struct pcmcia_socket *s); int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, - char *name, socket_info_t *s); + char *name, struct pcmcia_socket *s); int find_mem_region(u_long *base, u_long num, u_long align, - int force_low, char *name, socket_info_t *s); + int force_low, char *name, struct pcmcia_socket *s); int try_irq(u_int Attributes, int irq, int specific); void undo_irq(u_int Attributes, int irq); int adjust_resource_info(client_handle_t handle, adjust_t *adj); @@ -250,9 +178,8 @@ int proc_read_io(char *buf, char **start, off_t pos, int proc_read_mem(char *buf, char **start, off_t pos, int count, int *eof, void *data); -#define MAX_SOCK 8 -extern socket_t sockets; -extern socket_info_t *socket_table[MAX_SOCK]; +extern struct rw_semaphore pcmcia_socket_list_rwsem; +extern struct list_head pcmcia_socket_list; #ifdef CONFIG_PROC_FS extern struct proc_dir_entry *proc_pccard; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 8f4e8c2e8476f2c8814f4203dc6b0cd5066e4bef..b06d677a1dc3920fdc5fc1933935843fa9f82b4e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -107,8 +107,7 @@ struct pcmcia_bus_socket { struct work_struct removal; socket_bind_t *bind; struct device *socket_dev; - struct list_head socket_list; - unsigned int socket_no; /* deprecated */ + struct pcmcia_socket *parent; }; #define SOCKET_PRESENT 0x01 @@ -122,10 +121,6 @@ static dev_info_t dev_info = "Driver Services"; static int major_dev = -1; -/* list of all sockets registered with the pcmcia bus driver */ -static DECLARE_RWSEM(bus_socket_list_rwsem); -static LIST_HEAD(bus_socket_list); - extern struct proc_dir_entry *proc_pccard; /*====================================================================*/ @@ -164,20 +159,6 @@ EXPORT_SYMBOL(pcmcia_register_driver); */ void pcmcia_unregister_driver(struct pcmcia_driver *driver) { - socket_bind_t *b; - struct pcmcia_bus_socket *bus_sock; - - if (driver->use_count > 0) { - /* Blank out any left-over device instances */ - driver->attach = NULL; driver->detach = NULL; - down_read(&bus_socket_list_rwsem); - list_for_each_entry(bus_sock, &bus_socket_list, socket_list) { - for (b = bus_sock->bind; b; b = b->next) - if (b->driver == driver) - b->instance = NULL; - } - up_read(&bus_socket_list_rwsem); - } driver_unregister(&driver->drv); } EXPORT_SYMBOL(pcmcia_unregister_driver); @@ -319,14 +300,14 @@ static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info) bind_req.dev_info = &mtd_info->dev_info; bind_req.Attributes = mtd_info->Attributes; - bind_req.Socket = bus_sock->socket_no; + bind_req.Socket = bus_sock->parent; bind_req.CardOffset = mtd_info->CardOffset; ret = pcmcia_bind_mtd(&bind_req); if (ret != CS_SUCCESS) { cs_error(NULL, BindMTD, ret); printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d" " offset 0x%x\n", - (char *)bind_req.dev_info, bus_sock->socket_no, bind_req.CardOffset); + (char *)bind_req.dev_info, bus_sock->parent->sock, bind_req.CardOffset); return -ENODEV; } return 0; @@ -351,7 +332,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) if (!s) return -EINVAL; - DEBUG(2, "bind_request(%d, '%s')\n", s->socket_no, + DEBUG(2, "bind_request(%d, '%s')\n", s->parent->sock, (char *)bind_info->dev_info); driver = get_pcmcia_driver(&bind_info->dev_info); if (!driver) @@ -366,14 +347,18 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) return -EBUSY; } - bind_req.Socket = s->socket_no; + if (!try_module_get(driver->owner)) + return -EINVAL; + + bind_req.Socket = s->parent; bind_req.Function = bind_info->function; bind_req.dev_info = (dev_info_t *) driver->drv.name; ret = pcmcia_bind_device(&bind_req); if (ret != CS_SUCCESS) { cs_error(NULL, BindDevice, ret); printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n", - (char *)dev_info, s->socket_no); + (char *)dev_info, s->parent->sock); + module_put(driver->owner); return -ENODEV; } @@ -383,6 +368,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) if (!b) { driver->use_count--; + module_put(driver->owner); return -ENOMEM; } b->driver = driver; @@ -396,6 +382,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) if (b->instance == NULL) { printk(KERN_NOTICE "ds: unable to create instance " "of '%s'!\n", (char *)bind_info->dev_info); + module_put(driver->owner); return -ENODEV; } } @@ -476,7 +463,7 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) { socket_bind_t **b, *c; - DEBUG(2, "unbind_request(%d, '%s')\n", s->socket_no, + DEBUG(2, "unbind_request(%d, '%s')\n", s->parent->sock, (char *)bind_info->dev_info); for (b = &s->bind; *b; b = &(*b)->next) if ((strcmp((char *)(*b)->driver->drv.name, @@ -492,9 +479,9 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) if (c->instance) c->driver->detach(c->instance); } + module_put(c->driver->owner); *b = c->next; kfree(c); - return 0; } /* unbind_request */ @@ -832,13 +819,13 @@ static struct file_operations ds_fops = { .poll = ds_poll, }; -static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int socket_nr) +static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) { + struct pcmcia_socket *socket = class_dev->class_data; client_reg_t client_reg; bind_req_t bind; - struct pcmcia_bus_socket *s, *tmp_s; + struct pcmcia_bus_socket *s; int ret; - int i; s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL); if(!s) @@ -855,28 +842,15 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int sock init_waitqueue_head(&s->queue); init_waitqueue_head(&s->request); - /* find the lowest, unused socket no. Please note that this is a - * temporary workaround until "struct pcmcia_socket" is introduced - * into cs.c which will include this number, and which will be - * accessible to ds.c directly */ - i = 0; - next_try: - list_for_each_entry(tmp_s, &bus_socket_list, socket_list) { - if (tmp_s->socket_no == i) { - i++; - goto next_try; - } - } - s->socket_no = i; - /* initialize data */ - s->socket_dev = dev; + s->socket_dev = socket->dev.dev; INIT_WORK(&s->removal, handle_removal, s); - + s->parent = socket; + /* Set up hotline to Card Services */ client_reg.dev_info = bind.dev_info = &dev_info; - bind.Socket = s->socket_no; + bind.Socket = socket; bind.Function = BIND_FN_ALL; ret = pcmcia_bind_device(&bind); if (ret != CS_SUCCESS) { @@ -901,50 +875,26 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int sock return -EINVAL; } - list_add(&s->socket_list, &bus_socket_list); + socket->pcmcia = s; return 0; } -static int pcmcia_bus_add_socket_dev(struct class_device *class_dev) -{ - struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev); - unsigned int i; - unsigned int ret = 0; - - if (!cls_d) - return -ENODEV; - - down_write(&bus_socket_list_rwsem); - for (i = 0; i < cls_d->nsock; i++) - ret += pcmcia_bus_add_socket(class_dev->dev, i); - up_write(&bus_socket_list_rwsem); - - return ret; -} - -static void pcmcia_bus_remove_socket_dev(struct class_device *class_dev) +static void pcmcia_bus_remove_socket(struct class_device *class_dev) { - struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev); - struct list_head *list_loop; - struct list_head *tmp_storage; + struct pcmcia_socket *socket = class_dev->class_data; - if (!cls_d) + if (!socket || !socket->pcmcia) return; flush_scheduled_work(); - down_write(&bus_socket_list_rwsem); - list_for_each_safe(list_loop, tmp_storage, &bus_socket_list) { - struct pcmcia_bus_socket *bus_sock = container_of(list_loop, struct pcmcia_bus_socket, socket_list); - if (bus_sock->socket_dev == class_dev->dev) { - pcmcia_deregister_client(bus_sock->handle); - list_del(&bus_sock->socket_list); - kfree(bus_sock); - } - } - up_write(&bus_socket_list_rwsem); + pcmcia_deregister_client(socket->pcmcia->handle); + + kfree(socket->pcmcia); + socket->pcmcia = NULL; + return; } @@ -952,8 +902,8 @@ static void pcmcia_bus_remove_socket_dev(struct class_device *class_dev) /* the pcmcia_bus_interface is used to handle pcmcia socket devices */ static struct class_interface pcmcia_bus_interface = { .class = &pcmcia_socket_class, - .add = &pcmcia_bus_add_socket_dev, - .remove = &pcmcia_bus_remove_socket_dev, + .add = &pcmcia_bus_add_socket, + .remove = &pcmcia_bus_remove_socket, }; @@ -1008,18 +958,13 @@ module_exit(exit_pcmcia_bus); /* helpers for backwards-compatible functions */ - static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr) { - struct pcmcia_bus_socket * s; - down_read(&bus_socket_list_rwsem); - list_for_each_entry(s, &bus_socket_list, socket_list) - if (s->socket_no == nr) { - up_read(&bus_socket_list_rwsem); - return s; - } - up_read(&bus_socket_list_rwsem); - return NULL; + struct pcmcia_socket * s = pcmcia_get_socket_by_nr(nr); + if (s && s->pcmcia) + return s->pcmcia; + else + return NULL; } /* backwards-compatible accessing of driver --- by name! */ diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index f998ba48db4c1d40b33e98ca3c625c142720d3e5..d3591ae10ebee6a5e43a2a5b3d507b64265ffd53 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -44,14 +44,12 @@ MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state) { - struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev); - return pcmcia_socket_dev_suspend(cls_d, state, 0); + return pcmcia_socket_dev_suspend(&dev->dev, state, 0); } static int i82092aa_socket_resume (struct pci_dev *dev) { - struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev); - return pcmcia_socket_dev_resume(cls_d, RESUME_RESTORE_STATE); + return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE); } static struct pci_driver i82092aa_pci_drv = { @@ -82,6 +80,7 @@ static struct pccard_operations i82092aa_operations = { /* The card can do upto 4 sockets, allocate a structure for each of them */ struct socket_info { + int number; int card_state; /* 0 = no socket, 1 = empty socket, 2 = card but not initialized, @@ -95,6 +94,7 @@ struct socket_info { /* callback to the driver of the card */ void *info; /* to be passed to the handler */ + struct pcmcia_socket socket; struct pci_dev *dev; /* The PCI device for the socket */ }; @@ -107,7 +107,6 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic { unsigned char configbyte; int i, ret; - struct pcmcia_socket_class_data *cls_d; enter("i82092aa_pci_probe"); @@ -146,6 +145,8 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic sockets[i].cap.map_size = 0x1000; sockets[i].cap.irq_mask = 0; sockets[i].cap.pci_irq = dev->irq; + + sockets[i].number = i; if (card_present(i)) { sockets[i].card_state = 3; @@ -166,26 +167,26 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic goto err_out_free_res; } - - cls_d = kmalloc(sizeof(*cls_d), GFP_KERNEL); - if (!cls_d) { - printk(KERN_ERR "i82092aa: kmalloc failed\n"); - goto err_out_free_irq; + pci_set_drvdata(dev, &sockets[i].socket); + + for (i = 0; i<socket_count; i++) { + sockets[i].socket.dev.dev = &dev->dev; + sockets[i].socket.ss_entry = &i82092aa_operations; + ret = pcmcia_register_socket(&sockets[i].socket); + if (ret) { + goto err_out_free_sockets; + } } - memset(cls_d, 0, sizeof(*cls_d)); - cls_d->nsock = socket_count; - cls_d->ops = &i82092aa_operations; - pci_set_drvdata(dev, &cls_d); - cls_d->class_dev.class = &pcmcia_socket_class; - cls_d->class_dev.dev = &dev->dev; - strlcpy(cls_d->class_dev.class_id, dev->dev.name, BUS_ID_SIZE); - class_set_devdata(&cls_d->class_dev, cls_d); - class_device_register(&cls_d->class_dev); leave("i82092aa_pci_probe"); return 0; -err_out_free_irq: +err_out_free_sockets: + if (i) { + for (i--;i>=0;i--) { + pcmcia_unregister_socket(&sockets[i].socket); + } + } free_irq(dev->irq, i82092aa_interrupt); err_out_free_res: release_region(pci_resource_start(dev, 0), 2); @@ -196,16 +197,14 @@ static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_devic static void __devexit i82092aa_pci_remove(struct pci_dev *dev) { - struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev); + struct pcmcia_socket *socket = pci_get_drvdata(dev); enter("i82092aa_pci_remove"); free_irq(dev->irq, i82092aa_interrupt); - if (cls_d) { - class_device_unregister(&cls_d->class_dev); - kfree(cls_d); - } + if (socket) + pcmcia_unregister_socket(socket); leave("i82092aa_pci_remove"); } @@ -447,7 +446,7 @@ static void set_bridge_state(int sock) -static int i82092aa_init(unsigned int s) +static int i82092aa_init(struct pcmcia_socket *sock) { int i; pccard_io_map io = { 0, 0, 0, 0, 1 }; @@ -456,21 +455,21 @@ static int i82092aa_init(unsigned int s) enter("i82092aa_init"); mem.sys_stop = 0x0fff; - i82092aa_set_socket(s, &dead_socket); + i82092aa_set_socket(sock, &dead_socket); for (i = 0; i < 2; i++) { io.map = i; - i82092aa_set_io_map(s, &io); + i82092aa_set_io_map(sock, &io); } for (i = 0; i < 5; i++) { mem.map = i; - i82092aa_set_mem_map(s, &mem); + i82092aa_set_mem_map(sock, &mem); } leave("i82092aa_init"); return 0; } -static int i82092aa_suspend(unsigned int sock) +static int i82092aa_suspend(struct pcmcia_socket *sock) { int retval; enter("i82092aa_suspend"); @@ -479,8 +478,9 @@ static int i82092aa_suspend(unsigned int sock) return retval; } -static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info) +static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info) { + unsigned int sock = container_of(socket, struct socket_info, socket)->number; enter("i82092aa_register_callback"); sockets[sock].handler = handler; sockets[sock].info = info; @@ -488,8 +488,9 @@ static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, return 0; } /* i82092aa_register_callback */ -static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap) +static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap) { + unsigned int sock = container_of(socket, struct socket_info, socket)->number; enter("i82092aa_inquire_socket"); *cap = sockets[sock].cap; leave("i82092aa_inquire_socket"); @@ -497,8 +498,9 @@ static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap) } /* i82092aa_inquire_socket */ -static int i82092aa_get_status(unsigned int sock, u_int *value) +static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value) { + unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned int status; enter("i82092aa_get_status"); @@ -539,8 +541,9 @@ static int i82092aa_get_status(unsigned int sock, u_int *value) } -static int i82092aa_get_socket(unsigned int sock, socket_state_t *state) +static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state) { + unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned char reg,vcc,vpp; enter("i82092aa_get_socket"); @@ -610,8 +613,9 @@ static int i82092aa_get_socket(unsigned int sock, socket_state_t *state) return 0; } -static int i82092aa_set_socket(unsigned int sock, socket_state_t *state) +static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) { + unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned char reg; enter("i82092aa_set_socket"); @@ -706,8 +710,9 @@ static int i82092aa_set_socket(unsigned int sock, socket_state_t *state) return 0; } -static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io) +static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io) { + unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned char map, ioctl; enter("i82092aa_set_io_map"); @@ -749,8 +754,9 @@ static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io) return 0; } -static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem) +static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem) { + unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned short base, i; unsigned char map; @@ -826,7 +832,7 @@ static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem) return 0; } -static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base) +static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base) { } diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h index 191a3bd920971b519849095d82aede6888c9317f..eb1c307fbeff7109217bea407c1cc391e6df431a 100644 --- a/drivers/pcmcia/i82092aa.h +++ b/drivers/pcmcia/i82092aa.h @@ -28,16 +28,16 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs); -static int i82092aa_get_status(unsigned int sock, u_int *value); -static int i82092aa_get_socket(unsigned int sock, socket_state_t *state); -static int i82092aa_set_socket(unsigned int sock, socket_state_t *state); -static int i82092aa_set_io_map(unsigned int sock, struct pccard_io_map *io); -static int i82092aa_set_mem_map(unsigned int sock, struct pccard_mem_map *mem); -static int i82092aa_init(unsigned int s); -static int i82092aa_suspend(unsigned int sock); -static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info); -static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap); -static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base); +static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value); +static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state); +static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state); +static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io); +static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem); +static int i82092aa_init(struct pcmcia_socket *socket); +static int i82092aa_suspend(struct pcmcia_socket *socket); +static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info); +static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap); +static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base); #endif diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 560503d3917d9aa8e3e4b4f9a954af6299fab48d..c5536fe45702ab67954ceac6b2d84a064430fc64 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -91,7 +91,6 @@ static inline int _check_irq(int irq, int flags) /* Parameters that can be set with 'insmod' */ -#ifdef CONFIG_ISA /* Default base address for i82365sl and other ISA chips */ static int i365_base = 0x3e0; /* Should we probe at 0x3e2 for an extra ISA controller? */ @@ -103,7 +102,6 @@ static u_int irq_mask = 0xffff; static int irq_list[16] = { -1 }; /* The card status change interrupt -- 0 means autoselect */ static int cs_irq = 0; -#endif /* Probe for safe interrupts? */ static int do_scan = 1; @@ -122,14 +120,11 @@ static int setup_time = -1; static int cmd_time = -1; static int recov_time = -1; -#ifdef CONFIG_ISA /* Vadem options */ static int async_clock = -1; static int cable_mode = -1; static int wakeup = 0; -#endif -#ifdef CONFIG_ISA MODULE_PARM(i365_base, "i"); MODULE_PARM(ignore, "i"); MODULE_PARM(extra_sockets, "i"); @@ -139,7 +134,6 @@ MODULE_PARM(cs_irq, "i"); MODULE_PARM(async_clock, "i"); MODULE_PARM(cable_mode, "i"); MODULE_PARM(wakeup, "i"); -#endif MODULE_PARM(do_scan, "i"); MODULE_PARM(poll_interval, "i"); @@ -164,8 +158,10 @@ typedef struct vg46x_state_t { u_char ctl, ema; } vg46x_state_t; -typedef struct socket_info_t { +struct i82365_socket { u_short type, flags; + struct pcmcia_socket socket; + unsigned int number; socket_cap_t cap; ioaddr_t ioaddr; u_short psock; @@ -179,26 +175,21 @@ typedef struct socket_info_t { cirrus_state_t cirrus; vg46x_state_t vg46x; } state; -} socket_info_t; +}; /* Where we keep track of our sockets... */ static int sockets = 0; -static socket_info_t socket[8] = { +static struct i82365_socket socket[8] = { { 0, }, /* ... */ }; /* Default ISA interrupt mask */ #define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */ -#ifdef CONFIG_ISA static int grab_irq; static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED; #define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f) #define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f) -#else -#define ISA_LOCK(n, f) do { } while (0) -#define ISA_UNLOCK(n, f) do { } while (0) -#endif static struct timer_list poll_timer; @@ -209,13 +200,11 @@ static struct timer_list poll_timer; PCI_COMMAND_MASTER|PCI_COMMAND_WAIT) /* These definitions must match the pcic table! */ -#ifdef CONFIG_ISA typedef enum pcic_id { IS_I82365A, IS_I82365B, IS_I82365DF, IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469, IS_PD6710, IS_PD672X, IS_VT83C469, } pcic_id; -#endif /* Flags for classifying groups of controllers */ #define IS_VADEM 0x0001 @@ -237,7 +226,6 @@ typedef struct pcic_t { } pcic_t; static pcic_t pcic[] = { -#ifdef CONFIG_ISA { "Intel i82365sl A step", 0 }, { "Intel i82365sl B step", 0 }, { "Intel i82365sl DF", IS_DF_PWR }, @@ -249,7 +237,6 @@ static pcic_t pcic[] = { { "Cirrus PD6710", IS_CIRRUS }, { "Cirrus PD672x", IS_CIRRUS }, { "VIA VT83C469", IS_CIRRUS|IS_VIA }, -#endif }; #define PCIC_COUNT (sizeof(pcic)/sizeof(pcic_t)) @@ -364,7 +351,7 @@ static void cirrus_set_state(u_short s) static u_int __init cirrus_set_opts(u_short s, char *buf) { - socket_info_t *t = &socket[s]; + struct i82365_socket *t = &socket[s]; cirrus_state_t *p = &socket[s].state.cirrus; u_int mask = 0xffff; @@ -421,8 +408,6 @@ static u_int __init cirrus_set_opts(u_short s, char *buf) ======================================================================*/ -#ifdef CONFIG_ISA - static void vg46x_get_state(u_short s) { vg46x_state_t *p = &socket[s].state.vg46x; @@ -464,9 +449,6 @@ static u_int __init vg46x_set_opts(u_short s, char *buf) return 0xffff; } -#endif - - /*====================================================================== Generic routines to get and set controller options @@ -475,18 +457,16 @@ static u_int __init vg46x_set_opts(u_short s, char *buf) static void get_bridge_state(u_short s) { - socket_info_t *t = &socket[s]; + struct i82365_socket *t = &socket[s]; if (t->flags & IS_CIRRUS) cirrus_get_state(s); -#ifdef CONFIG_ISA else if (t->flags & IS_VADEM) vg46x_get_state(s); -#endif } static void set_bridge_state(u_short s) { - socket_info_t *t = &socket[s]; + struct i82365_socket *t = &socket[s]; if (t->flags & IS_CIRRUS) cirrus_set_state(s); else { @@ -494,10 +474,8 @@ static void set_bridge_state(u_short s) i365_set(s, I365_GENCTL, 0x00); } i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr); -#ifdef CONFIG_ISA if (t->flags & IS_VADEM) vg46x_set_state(s); -#endif } static u_int __init set_bridge_opts(u_short s, u_short ns) @@ -515,10 +493,8 @@ static u_int __init set_bridge_opts(u_short s, u_short ns) get_bridge_state(i); if (socket[i].flags & IS_CIRRUS) m = cirrus_set_opts(i, buf); -#ifdef CONFIG_ISA else if (socket[i].flags & IS_VADEM) m = vg46x_set_opts(i, buf); -#endif set_bridge_state(i); printk(KERN_INFO " host opts [%d]:%s\n", i, (*buf) ? buf : " none"); @@ -571,7 +547,6 @@ static u_int __init test_irq(u_short sock, int irq) return (irq_hits != 1); } -#ifdef CONFIG_ISA static u_int __init isa_scan(u_short sock, u_int mask0) { @@ -617,7 +592,6 @@ static u_int __init isa_scan(u_short sock, u_int mask0) return mask1; } -#endif /* CONFIG_ISA */ /*====================================================================*/ @@ -630,7 +604,6 @@ static int to_cycles(int ns) /*====================================================================*/ -#ifdef CONFIG_ISA static int __init identify(u_short port, u_short sock) { @@ -691,8 +664,6 @@ static int __init identify(u_short port, u_short sock) return type; } /* identify */ -#endif - /*====================================================================== See if a card is present, powered up, in IO mode, and already @@ -737,7 +708,7 @@ static void __init add_pcic(int ns, int type) { u_int mask = 0, i, base; int use_pci = 0, isa_irq = 0; - socket_info_t *t = &socket[sockets-ns]; + struct i82365_socket *t = &socket[sockets-ns]; base = sockets-ns; if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365"); @@ -748,23 +719,17 @@ static void __init add_pcic(int ns, int type) t->ioaddr, t->psock*0x40); printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : "")); -#ifdef CONFIG_ISA /* Set host options, build basic interrupt mask */ if (irq_list[0] == -1) mask = irq_mask; else for (i = mask = 0; i < 16; i++) mask |= (1<<irq_list[i]); -#endif mask &= I365_MASK & set_bridge_opts(base, ns); -#ifdef CONFIG_ISA /* Scan for ISA interrupts */ mask = isa_scan(base, mask); -#else printk(KERN_INFO " PCI card interrupts,"); -#endif -#ifdef CONFIG_ISA /* Poll if only two interrupts available */ if (!use_pci && !poll_interval) { u_int tmp = (mask & 0xff20); @@ -786,7 +751,6 @@ static void __init add_pcic(int ns, int type) printk(" status change on irq %d\n", cs_irq); } } -#endif if (!use_pci && !isa_irq) { if (poll_interval == 0) @@ -809,7 +773,6 @@ static void __init add_pcic(int ns, int type) /*====================================================================*/ -#ifdef CONFIG_ISA #ifdef CONFIG_PNP static struct isapnp_device_id id_table[] __initdata = { @@ -902,7 +865,6 @@ static void __init isa_probe(void) } } -#endif /*====================================================================*/ @@ -940,9 +902,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev, { int i, j, csc; u_int events, active; -#ifdef CONFIG_ISA u_long flags = 0; -#endif int handled = 0; DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq); @@ -1013,8 +973,9 @@ static void pcic_interrupt_wrapper(u_long data) /*====================================================================*/ -static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info) +static int pcic_register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info) { + unsigned int sock = container_of(s, struct i82365_socket, socket)->number; socket[sock].handler = handler; socket[sock].info = info; return 0; @@ -1022,8 +983,9 @@ static int pcic_register_callback(unsigned int sock, void (*handler)(void *, uns /*====================================================================*/ -static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap) +static int pcic_inquire_socket(struct pcmcia_socket *s, socket_cap_t *cap) { + unsigned int sock = container_of(s, struct i82365_socket, socket)->number; *cap = socket[sock].cap; return 0; } /* pcic_inquire_socket */ @@ -1048,7 +1010,6 @@ static int i365_get_status(u_short sock, u_int *value) *value |= (status & I365_CS_READY) ? SS_READY : 0; *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0; -#ifdef CONFIG_ISA if (socket[sock].type == IS_VG469) { status = i365_get(sock, VG469_VSENSE); if (socket[sock].psock & 1) { @@ -1059,7 +1020,6 @@ static int i365_get_status(u_short sock, u_int *value) *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD; } } -#endif DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value); return 0; @@ -1069,7 +1029,7 @@ static int i365_get_status(u_short sock, u_int *value) static int i365_get_socket(u_short sock, socket_state_t *state) { - socket_info_t *t = &socket[sock]; + struct i82365_socket *t = &socket[sock]; u_char reg, vcc, vpp; reg = i365_get(sock, I365_POWER); @@ -1141,7 +1101,7 @@ static int i365_get_socket(u_short sock, socket_state_t *state) static int i365_set_socket(u_short sock, socket_state_t *state) { - socket_info_t *t = &socket[sock]; + struct i82365_socket *t = &socket[sock]; u_char reg; DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " @@ -1337,7 +1297,7 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) static int proc_read_info(char *buf, char **start, off_t pos, int count, int *eof, void *data) { - socket_info_t *s = data; + struct i82365_socket *s = data; char *p = buf; p += sprintf(p, "type: %s\npsock: %d\n", pcic[s->type].name, s->psock); @@ -1347,13 +1307,11 @@ static int proc_read_info(char *buf, char **start, off_t pos, static int proc_read_exca(char *buf, char **start, off_t pos, int count, int *eof, void *data) { - u_short sock = (socket_info_t *)data - socket; + u_short sock = (struct i82365_socket *)data - socket; char *p = buf; int i, top; -#ifdef CONFIG_ISA u_long flags = 0; -#endif ISA_LOCK(sock, flags); top = 0x40; for (i = 0; i < top; i += 4) { @@ -1370,9 +1328,9 @@ static int proc_read_exca(char *buf, char **start, off_t pos, return (p - buf); } -static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base) +static void pcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base) { - socket_info_t *s = &socket[sock]; + struct i82365_socket *s = container_of(sock, struct i82365_socket, socket); if (s->flags & IS_ALIVE) return; @@ -1398,15 +1356,8 @@ static void pcic_proc_remove(u_short sock) /*====================================================================*/ -/* - * The locking is rather broken. Why do we only lock for ISA, not for - * all other cases? If there are reasons to lock, we should lock. Not - * this silly conditional. - * - * Plan: make it bug-for-bug compatible with the old stuff, and clean - * it up when the infrastructure is done. - */ -#ifdef CONFIG_ISA +/* this is horribly ugly... proper locking needs to be done here at + * some time... */ #define LOCKED(x) do { \ int retval; \ unsigned long flags; \ @@ -1415,13 +1366,12 @@ static void pcic_proc_remove(u_short sock) spin_unlock_irqrestore(&isa_lock, flags); \ return retval; \ } while (0) -#else -#define LOCKED(x) return x -#endif -static int pcic_get_status(unsigned int sock, u_int *value) +static int pcic_get_status(struct pcmcia_socket *s, u_int *value) { + unsigned int sock = container_of(s, struct i82365_socket, socket)->number; + if (socket[sock].flags & IS_ALIVE) { *value = 0; return -EINVAL; @@ -1430,39 +1380,45 @@ static int pcic_get_status(unsigned int sock, u_int *value) LOCKED(i365_get_status(sock, value)); } -static int pcic_get_socket(unsigned int sock, socket_state_t *state) +static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state) { + unsigned int sock = container_of(s, struct i82365_socket, socket)->number; + if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_get_socket(sock, state)); } -static int pcic_set_socket(unsigned int sock, socket_state_t *state) +static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state) { + unsigned int sock = container_of(s, struct i82365_socket, socket)->number; + if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_set_socket(sock, state)); } -static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io) +static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) { + unsigned int sock = container_of(s, struct i82365_socket, socket)->number; if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_set_io_map(sock, io)); } -static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) +static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) { + unsigned int sock = container_of(s, struct i82365_socket, socket)->number; if (socket[sock].flags & IS_ALIVE) return -EINVAL; LOCKED(i365_set_mem_map(sock, mem)); } -static int pcic_init(unsigned int s) +static int pcic_init(struct pcmcia_socket *s) { int i; pccard_io_map io = { 0, 0, 0, 0, 1 }; @@ -1481,7 +1437,7 @@ static int pcic_init(unsigned int s) return 0; } -static int pcic_suspend(unsigned int sock) +static int pcic_suspend(struct pcmcia_socket *sock) { return pcic_set_socket(sock, &dead_socket); } @@ -1502,15 +1458,11 @@ static struct pccard_operations pcic_operations = { /*====================================================================*/ -static struct pcmcia_socket_class_data i82365_data = { - .ops = &pcic_operations, -}; - static struct device_driver i82365_driver = { .name = "i82365", .bus = &platform_bus_type, -/* .suspend = pcmcia_socket_dev_suspend, FIXME? */ -/* .resume = pcmcia_socket_dev_resume, FIXME? */ + .suspend = pcmcia_socket_dev_suspend, + .resume = pcmcia_socket_dev_resume, }; static struct platform_device i82365_device = { @@ -1521,13 +1473,11 @@ static struct platform_device i82365_device = { }, }; -static struct class_device i82365_class_data = { - .class = &pcmcia_socket_class, -}; - static int __init init_i82365(void) { servinfo_t serv; + int i, ret; + pcmcia_get_card_services_info(&serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "i82365: Card Services release " @@ -1541,9 +1491,7 @@ static int __init init_i82365(void) printk(KERN_INFO "Intel PCIC probe: "); sockets = 0; -#ifdef CONFIG_ISA isa_probe(); -#endif if (sockets == 0) { printk("not found.\n"); @@ -1551,19 +1499,24 @@ static int __init init_i82365(void) return -ENODEV; } + platform_device_register(&i82365_device); + /* Set up interrupt handler(s) */ -#ifdef CONFIG_ISA if (grab_irq != 0) request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt); -#endif - i82365_data.nsock = sockets; - i82365_class_data.dev = &i82365_device.dev; - i82365_class_data.class_data = &i82365_data; - strlcpy(i82365_class_data.class_id, "i82365", BUS_ID_SIZE); - - platform_device_register(&i82365_device); - class_device_register(&i82365_class_data); + /* register sockets with the pcmcia core */ + for (i = 0; i < sockets; i++) { + socket[i].socket.dev.dev = &i82365_device.dev; + socket[i].socket.ss_entry = &pcic_operations; + socket[i].number = i; + ret = pcmcia_register_socket(&socket[i].socket); + if (ret && i--) { + for (; i>= 0; i--) + pcmcia_unregister_socket(&socket[i].socket); + break; + } + } /* Finally, schedule a polling interrupt */ if (poll_interval != 0) { @@ -1581,23 +1534,23 @@ static int __init init_i82365(void) static void __exit exit_i82365(void) { int i; + for (i = 0; i < sockets; i++) { + pcmcia_unregister_socket(&socket[i].socket); #ifdef CONFIG_PROC_FS - for (i = 0; i < sockets; i++) pcic_proc_remove(i); + pcic_proc_remove(i); #endif - class_device_unregister(&i82365_class_data); + } platform_device_unregister(&i82365_device); if (poll_interval != 0) del_timer_sync(&poll_timer); -#ifdef CONFIG_ISA if (grab_irq != 0) free_irq(cs_irq, pcic_interrupt); -#endif for (i = 0; i < sockets; i++) { /* Turn off all interrupt sources! */ i365_set(i, I365_CSCINT, 0); release_region(socket[i].ioaddr, 2); } -#if defined(CONFIG_ISA) && defined(__ISAPNP__) +#ifdef __ISAPNP__ if (i82365_pnpdev) pnp_disable_dev(i82365_pnpdev); #endif diff --git a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c deleted file mode 100644 index 915a6af9facab1feacfb81497a1bb28c7cd034e1..0000000000000000000000000000000000000000 --- a/drivers/pcmcia/pci_socket.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * 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/workqueue.h> -#include <linux/interrupt.h> -#include <linux/device.h> - -#include <pcmcia/ss.h> - -#include <asm/io.h> - -#include "pci_socket.h" - - -/* - * 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; - 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_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_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 = { - .owner = THIS_MODULE, - .init = pci_init_socket, - .suspend = pci_suspend_socket, - .register_callback = pci_register_callback, - .inquire_socket = pci_inquire_socket, - .get_status = pci_get_status, - .get_socket = pci_get_socket, - .set_socket = pci_set_socket, - .set_io_map = pci_set_io_map, - .set_mem_map = pci_set_mem_map, - .proc_setup = 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)); - - /* prepare class_data */ - socket->cls_d.sock_offset = nr; - socket->cls_d.nsock = 1; /* yenta is 1, no other low-level driver uses - this yet */ - socket->cls_d.ops = &pci_socket_operations; - socket->cls_d.class_dev.class = &pcmcia_socket_class; - socket->cls_d.class_dev.dev = &dev->dev; - strlcpy(socket->cls_d.class_dev.class_id, dev->dev.bus_id, BUS_ID_SIZE); - class_set_devdata(&socket->cls_d.class_dev, &socket->cls_d); - - /* prepare pci_socket_t */ - 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); - } else { - class_device_register(&socket->cls_d.class_dev); - } - return err; -} - -int cardbus_register(struct pci_dev *p_dev) -{ - return 0; -} - -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); - - /* note: we are already unregistered from the cs core */ - class_device_unregister(&socket->cls_d.class_dev); - 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); - return pcmcia_socket_dev_suspend(&socket->cls_d, state, 0); -} - -static int cardbus_resume (struct pci_dev *dev) -{ - pci_socket_t *socket = pci_get_drvdata(dev); - return pcmcia_socket_dev_resume(&socket->cls_d, RESUME_RESTORE_STATE); -} - - -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_register_driver (&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); diff --git a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h deleted file mode 100644 index 206eddd05c11a7976885c98f651974dfae0f5f35..0000000000000000000000000000000000000000 --- a/drivers/pcmcia/pci_socket.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * drivers/pcmcia/pci_socket.h - * - * (C) Copyright 1999 Linus Torvalds - */ - -#ifndef __PCI_SOCKET_H -#define __PCI_SOCKET_H - -struct pci_socket_ops; -struct socket_info_t; - -typedef struct pci_socket { - struct pci_dev *dev; - int cb_irq, io_irq; - void *base; - void (*handler)(void *, unsigned int); - void *info; - struct pci_socket_ops *op; - socket_cap_t cap; - spinlock_t event_lock; - unsigned int events; - struct work_struct tq_task; - struct timer_list poll_timer; - - struct pcmcia_socket_class_data cls_d; - /* A few words of private data for the low-level driver.. */ - unsigned int private[8]; -} pci_socket_t; - -struct pci_socket_ops { - int (*open)(struct pci_socket *); - void (*close)(struct pci_socket *); - - int (*init)(struct pci_socket *); - int (*suspend)(struct pci_socket *); - int (*get_status)(struct pci_socket *, unsigned int *); - int (*get_socket)(struct pci_socket *, socket_state_t *); - int (*set_socket)(struct pci_socket *, socket_state_t *); - int (*set_io_map)(struct pci_socket *, struct pccard_io_map *); - int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *); - void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base); -}; - -extern struct pci_socket_ops yenta_operations; -extern struct pci_socket_ops ricoh_operations; - -#endif diff --git a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h index 14573f8d3646eae1f5be429318efd85a4edd1994..a36f2f339d4245f6686e523c06fcbff43256d809 100644 --- a/drivers/pcmcia/ricoh.h +++ b/drivers/pcmcia/ricoh.h @@ -125,11 +125,26 @@ #define rl_mem(socket) ((socket)->private[3]) #define rl_config(socket) ((socket)->private[4]) +static int ricoh_init(struct pcmcia_socket *sock) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + yenta_init(sock); + + config_writew(socket, RL5C4XX_MISC, rl_misc(socket)); + config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket)); + config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket)); + config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket)); + config_writew(socket, RL5C4XX_CONFIG, rl_config(socket)); + + return 0; +} + + /* * Magic Ricoh initialization code.. Save state at * beginning, re-initialize it after suspend. */ -static int ricoh_open(pci_socket_t *socket) +static int ricoh_override(struct yenta_socket *socket) { rl_misc(socket) = config_readw(socket, RL5C4XX_MISC); rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL); @@ -146,35 +161,11 @@ static int ricoh_open(pci_socket_t *socket) rl_config(socket) |= RL5C4XX_CONFIG_PREFETCH; } - return 0; -} - -static int ricoh_init(pci_socket_t *socket) -{ - yenta_init(socket); + socket->socket.ss_entry->init = ricoh_init; - config_writew(socket, RL5C4XX_MISC, rl_misc(socket)); - config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket)); - config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket)); - config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket)); - config_writew(socket, RL5C4XX_CONFIG, rl_config(socket)); - return 0; } -static struct pci_socket_ops ricoh_ops = { - ricoh_open, - yenta_close, - ricoh_init, - yenta_suspend, - yenta_get_status, - yenta_get_socket, - yenta_set_socket, - yenta_set_io_map, - yenta_set_mem_map, - yenta_proc_setup -}; - #endif /* CONFIG_CARDBUS */ #endif /* _LINUX_RICOH_H */ diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 36e15cfdd73c42e698745bdaa797c33a3376e41b..9d962c2c1545b6bb69ce5fd455eed89ba5e2ec40 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -90,7 +90,7 @@ static DECLARE_MUTEX(rsrc_sem); typedef struct irq_info_t { u_int Attributes; int time_share, dyn_share; - struct socket_info_t *Socket; + struct pcmcia_socket *Socket; } irq_info_t; /* Table of IRQ assignments */ @@ -341,7 +341,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) ======================================================================*/ /* Validation function for cards with a valid CIS */ -static int cis_readable(socket_info_t *s, u_long base) +static int cis_readable(struct pcmcia_socket *s, u_long base) { cisinfo_t info1, info2; int ret; @@ -364,7 +364,7 @@ static int cis_readable(socket_info_t *s, u_long base) } /* Validation function for simple memory cards */ -static int checksum(socket_info_t *s, u_long base) +static int checksum(struct pcmcia_socket *s, u_long base) { int i, a, b, d; s->cis_mem.sys_start = base; @@ -372,7 +372,7 @@ static int checksum(socket_info_t *s, u_long base) s->cis_virt = ioremap(base, s->cap.map_size); s->cis_mem.card_start = 0; s->cis_mem.flags = MAP_ACTIVE; - s->ss_entry->set_mem_map(s->sock, &s->cis_mem); + s->ss_entry->set_mem_map(s, &s->cis_mem); /* Don't bother checking every word... */ a = 0; b = -1; for (i = 0; i < s->cap.map_size; i += 44) { @@ -383,7 +383,7 @@ static int checksum(socket_info_t *s, u_long base) return (b == -1) ? -1 : (a>>1); } -static int checksum_match(socket_info_t *s, u_long base) +static int checksum_match(struct pcmcia_socket *s, u_long base) { int a = checksum(s, base), b = checksum(s, base+s->cap.map_size); return ((a == b) && (a >= 0)); @@ -397,7 +397,7 @@ static int checksum_match(socket_info_t *s, u_long base) ======================================================================*/ -static int do_mem_probe(u_long base, u_long num, socket_info_t *s) +static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) { u_long i, j, bad, fail, step; @@ -435,7 +435,7 @@ static int do_mem_probe(u_long base, u_long num, socket_info_t *s) #ifdef CONFIG_PCMCIA_PROBE -static u_long inv_probe(resource_map_t *m, socket_info_t *s) +static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s) { u_long ok; if (m == &mem_db) @@ -451,7 +451,7 @@ static u_long inv_probe(resource_map_t *m, socket_info_t *s) return do_mem_probe(m->base, m->num, s); } -void validate_mem(socket_info_t *s) +void validate_mem(struct pcmcia_socket *s) { resource_map_t *m, *n; static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; @@ -497,7 +497,7 @@ void validate_mem(socket_info_t *s) #else /* CONFIG_PCMCIA_PROBE */ -void validate_mem(socket_info_t *s) +void validate_mem(struct pcmcia_socket *s) { resource_map_t *m, *n; static int done = 0; @@ -529,7 +529,7 @@ void validate_mem(socket_info_t *s) ======================================================================*/ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, - char *name, socket_info_t *s) + char *name, struct pcmcia_socket *s) { ioaddr_t try; resource_map_t *m; @@ -556,7 +556,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, } int find_mem_region(u_long *base, u_long num, u_long align, - int force_low, char *name, socket_info_t *s) + int force_low, char *name, struct pcmcia_socket *s) { u_long try; resource_map_t *m; @@ -726,7 +726,7 @@ void undo_irq(u_int Attributes, int irq) static int adjust_memory(adjust_t *adj) { u_long base, num; - int i, ret; + int ret; base = adj->resource.memory.Base; num = adj->resource.memory.Size; @@ -743,9 +743,11 @@ static int adjust_memory(adjust_t *adj) case REMOVE_MANAGED_RESOURCE: ret = sub_interval(&mem_db, base, num); if (ret == CS_SUCCESS) { - for (i = 0; i < sockets; i++) { - release_cis_mem(socket_table[i]); - } + struct pcmcia_socket *socket; + down_read(&pcmcia_socket_list_rwsem); + list_for_each_entry(socket, &pcmcia_socket_list, socket_list) + release_cis_mem(socket); + up_read(&pcmcia_socket_list_rwsem); } break; default: diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index 6ddba61ba2d843b40312590c45494222329ed6b4..dee5cdcf82d72a68510f1ae1831e20c8ad6964ec 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -106,19 +106,10 @@ static struct device_driver sa11x0_pcmcia_driver = { .remove = sa11xx_drv_pcmcia_remove, .name = "sa11x0-pcmcia", .bus = &platform_bus_type, - .devclass = &pcmcia_socket_class, .suspend = pcmcia_socket_dev_suspend, .resume = pcmcia_socket_dev_resume, }; -static struct platform_device sa11x0_pcmcia_device = { - .name = "sa11x0-pcmcia", - .id = 0, - .dev = { - .name = "Intel Corporation SA11x0 [PCMCIA]", - }, -}; - /* sa11x0_pcmcia_init() * ^^^^^^^^^^^^^^^^^^^^ * @@ -129,16 +120,7 @@ static struct platform_device sa11x0_pcmcia_device = { */ static int __init sa11x0_pcmcia_init(void) { - int ret; - - ret = driver_register(&sa11x0_pcmcia_driver); - if (ret == 0) { - ret = platform_device_register(&sa11x0_pcmcia_device); - if (ret) - driver_unregister(&sa11x0_pcmcia_driver); - } - - return ret; + return driver_register(&sa11x0_pcmcia_driver); } /* sa11x0_pcmcia_exit() @@ -148,7 +130,6 @@ static int __init sa11x0_pcmcia_init(void) */ static void __exit sa11x0_pcmcia_exit(void) { - platform_device_unregister(&sa11x0_pcmcia_device); driver_unregister(&sa11x0_pcmcia_driver); } diff --git a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/sa11xx_core.c index 102203779a22f16c20784b77f15388b1e22d683d..cfe9b4e2368e746a62caeef54fbc26133f1af19b 100644 --- a/drivers/pcmcia/sa11xx_core.c +++ b/drivers/pcmcia/sa11xx_core.c @@ -69,6 +69,8 @@ static struct sa1100_pcmcia_socket sa1100_pcmcia_socket[SA1100_PCMCIA_MAX_SOCK]; #define PCMCIA_SOCKET(x) (sa1100_pcmcia_socket + (x)) +#define to_sa1100_socket(x) container_of(x, struct sa1100_pcmcia_socket, socket) + /* * sa1100_pcmcia_default_mecr_timing * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -226,9 +228,9 @@ sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state * * Returns: 0 */ -static int sa1100_pcmcia_sock_init(unsigned int sock) +static int sa1100_pcmcia_sock_init(struct pcmcia_socket *sock) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, skt->nr); @@ -248,9 +250,9 @@ static int sa1100_pcmcia_sock_init(unsigned int sock) * * Returns: 0 */ -static int sa1100_pcmcia_suspend(unsigned int sock) +static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); int ret; DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, skt->nr); @@ -348,11 +350,11 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r * Returns: 0 */ static int -sa1100_pcmcia_register_callback(unsigned int sock, +sa1100_pcmcia_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void *info) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); if (handler) { if (!try_module_get(skt->ops->owner)) @@ -392,9 +394,9 @@ sa1100_pcmcia_register_callback(unsigned int sock, * Return value is irrelevant; the pcmcia subsystem ignores it. */ static int -sa1100_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap) +sa1100_pcmcia_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); int ret = -1; if (skt) { @@ -430,9 +432,9 @@ sa1100_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap) * Returns: 0 */ static int -sa1100_pcmcia_get_status(unsigned int sock, unsigned int *status) +sa1100_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); skt->status = sa1100_pcmcia_skt_state(skt); *status = skt->status; @@ -450,9 +452,9 @@ sa1100_pcmcia_get_status(unsigned int sock, unsigned int *status) * Returns: 0 */ static int -sa1100_pcmcia_get_socket(unsigned int sock, socket_state_t *state) +sa1100_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr); @@ -472,9 +474,9 @@ sa1100_pcmcia_get_socket(unsigned int sock, socket_state_t *state) * Returns: 0 */ static int -sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state) +sa1100_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr); @@ -508,9 +510,9 @@ sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state) * Returns: 0 on success, -1 on error */ static int -sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) +sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); unsigned short speed = map->speed; DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr); @@ -564,9 +566,9 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) * Returns: 0 on success, -1 on error */ static int -sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) +sa1100_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); + struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); struct resource *res; unsigned short speed = map->speed; @@ -708,7 +710,7 @@ sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos, * Returns: 0 on success, -1 on error */ static void -sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base) +sa1100_pcmcia_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base) { struct proc_dir_entry *entry; @@ -717,7 +719,7 @@ sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base) return; } entry->read_proc = sa1100_pcmcia_proc_status; - entry->data = PCMCIA_SOCKET(sock); + entry->data = to_sa1100_socket(sock); } #else #define sa1100_pcmcia_proc_setup NULL @@ -800,22 +802,16 @@ static const char *skt_names[] = { "PCMCIA socket 1", }; +struct skt_dev_info { + int nskt; +}; + int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) { - struct pcmcia_socket_class_data *cls; + struct skt_dev_info *sinfo; unsigned int cpu_clock; int ret, i; - cls = kmalloc(sizeof(struct pcmcia_socket_class_data), GFP_KERNEL); - if (!cls) { - ret = -ENOMEM; - goto out; - } - - memset(cls, 0, sizeof(struct pcmcia_socket_class_data)); - cls->ops = &sa11xx_pcmcia_operations; - cls->nsock = nr; - /* * set default MECR calculation if the board specific * code did not specify one... @@ -823,6 +819,15 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in if (!ops->socket_get_timing) ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing; + sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL); + if (!sinfo) { + ret = -ENOMEM; + goto out; + } + + memset(sinfo, 0, sizeof(struct skt_dev_info)); + sinfo->nskt = nr; + cpu_clock = cpufreq_get(0); /* @@ -832,6 +837,9 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); memset(skt, 0, sizeof(*skt)); + skt->socket.ss_entry = &sa11xx_pcmcia_operations; + skt->socket.dev.dev = dev; + INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt); init_timer(&skt->poll_timer); @@ -898,16 +906,26 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in goto out_err_6; skt->status = sa1100_pcmcia_skt_state(skt); + + ret = pcmcia_register_socket(&skt->socket); + if (ret) + goto out_err_7; + + WARN_ON(skt->socket.sock != i); + add_timer(&skt->poll_timer); } - dev->class_data = cls; + dev_set_drvdata(dev, sinfo); return 0; do { struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); del_timer_sync(&skt->poll_timer); + pcmcia_unregister_socket(&skt->socket); + + out_err_7: flush_scheduled_work(); ops->hw_shutdown(skt); @@ -925,7 +943,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in i--; } while (i > 0); - kfree(cls); + kfree(sinfo); out: return ret; @@ -934,19 +952,22 @@ EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); int sa11xx_drv_pcmcia_remove(struct device *dev) { - struct pcmcia_socket_class_data *cls = dev->class_data; + struct skt_dev_info *sinfo = dev_get_drvdata(dev); int i; - dev->class_data = NULL; - - for (i = 0; i < cls->nsock; i++) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(cls->sock_offset + i); + dev_set_drvdata(dev, NULL); - skt->ops->hw_shutdown(skt); + for (i = 0; i < sinfo->nskt; i++) { + struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); del_timer_sync(&skt->poll_timer); + + pcmcia_unregister_socket(&skt->socket); + flush_scheduled_work(); + skt->ops->hw_shutdown(skt); + sa1100_pcmcia_config_skt(skt, &dead_socket); iounmap(skt->virt_io); @@ -957,7 +978,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev) release_resource(&skt->res_skt); } - kfree(cls); + kfree(sinfo); return 0; } @@ -977,7 +998,8 @@ static void sa1100_pcmcia_update_mecr(unsigned int clock) for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) { struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); - sa1100_pcmcia_set_mecr(skt, clock); + if (skt->ops) + sa1100_pcmcia_set_mecr(skt, clock); } } diff --git a/drivers/pcmcia/sa11xx_core.h b/drivers/pcmcia/sa11xx_core.h index 570491f2d96de211a8137e9ff8d8f6f7c324abf7..210228ddf75285c4d5404981e5426eab9b28d7a2 100644 --- a/drivers/pcmcia/sa11xx_core.h +++ b/drivers/pcmcia/sa11xx_core.h @@ -44,6 +44,8 @@ struct pcmcia_state { * use when responding to a Card Services query of some kind. */ struct sa1100_pcmcia_socket { + struct pcmcia_socket socket; + /* * Info from low level handler */ diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index b85d5c8468d6018a6754de718c732a1a52394cd9..648d38c57583295cecbbb6b286c7359bb7bd8143 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -115,19 +115,20 @@ static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs); static void tcic_timer(u_long data); static struct pccard_operations tcic_operations; -typedef struct socket_info_t { +struct tcic_socket { u_short psock; void (*handler)(void *info, u_int events); void *info; u_char last_sstat; u_char id; -} socket_info_t; + struct pcmcia_socket socket; +}; static struct timer_list poll_timer; static int tcic_timer_pending; static int sockets; -static socket_info_t socket_table[2]; +static struct tcic_socket socket_table[2]; static socket_cap_t tcic_cap = { /* only 16-bit cards, memory windows must be size-aligned */ @@ -372,15 +373,11 @@ static int __init get_tcic_id(void) /*====================================================================*/ -static struct pcmcia_socket_class_data tcic_data = { - .ops = &tcic_operations, -}; - static struct device_driver tcic_driver = { .name = "tcic-pcmcia", .bus = &platform_bus_type, -/* .suspend = pcmcia_socket_dev_suspend, FIXME? */ -/* .resume = pcmcia_socket_dev_resume, FIXME? */ + .suspend = pcmcia_socket_dev_suspend, + .resume = pcmcia_socket_dev_resume, }; static struct platform_device tcic_device = { @@ -391,13 +388,10 @@ static struct platform_device tcic_device = { }, }; -static struct class_device tcic_class_data = { - .class = &pcmcia_socket_class, -}; static int __init init_tcic(void) { - int i, sock; + int i, sock, ret = 0; u_int mask, scan; servinfo_t serv; @@ -524,13 +518,17 @@ static int __init init_tcic(void) /* jump start interrupt handler, if needed */ tcic_interrupt(0, NULL, NULL); - tcic_data.nsock = sockets; - tcic_class_data.dev = &tcic_device.dev; - tcic_class_data.class_data = &tcic_data; - strlcpy(tcic_class_data.class_id, "tcic-pcmcia", BUS_ID_SIZE); - platform_device_register(&tcic_device); - class_device_register(&tcic_class_data); + + for (i = 0; i < sockets; i++) { + socket_table[i].socket.ss_entry = &tcic_operations; + socket_table[i].socket.dev.dev = &tcic_device.dev; + ret = pcmcia_register_socket(&socket_table[i].socket); + if (ret && i) + pcmcia_unregister_socket(&socket_table[0].socket); + } + + return ret; return 0; @@ -540,13 +538,19 @@ static int __init init_tcic(void) static void __exit exit_tcic(void) { + int i; + del_timer_sync(&poll_timer); if (cs_irq != 0) { tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00); free_irq(cs_irq, tcic_interrupt); } release_region(tcic_base, 16); - class_device_unregister(&tcic_class_data); + + for (i = 0; i < sockets; i++) { + pcmcia_unregister_socket(&socket_table[i].socket); + } + platform_device_unregister(&tcic_device); driver_unregister(&tcic_driver); } /* exit_tcic */ @@ -640,18 +644,19 @@ static void tcic_timer(u_long data) /*====================================================================*/ -static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info) +static int tcic_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info) { - socket_table[lsock].handler = handler; - socket_table[lsock].info = info; + u_short psock = container_of(sock, struct tcic_socket, socket)->psock; + socket_table[psock].handler = handler; + socket_table[psock].info = info; return 0; } /* tcic_register_callback */ /*====================================================================*/ -static int tcic_get_status(unsigned int lsock, u_int *value) +static int tcic_get_status(struct pcmcia_socket *sock, u_int *value) { - u_short psock = socket_table[lsock].psock; + u_short psock = container_of(sock, struct tcic_socket, socket)->psock; u_char reg; tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT) @@ -675,7 +680,7 @@ static int tcic_get_status(unsigned int lsock, u_int *value) /*====================================================================*/ -static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap) +static int tcic_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap) { *cap = tcic_cap; return 0; @@ -683,9 +688,9 @@ static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap) /*====================================================================*/ -static int tcic_get_socket(unsigned int lsock, socket_state_t *state) +static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state) { - u_short psock = socket_table[lsock].psock; + u_short psock = container_of(sock, struct tcic_socket, socket)->psock; u_char reg; u_short scf1, scf2; @@ -736,9 +741,9 @@ static int tcic_get_socket(unsigned int lsock, socket_state_t *state) /*====================================================================*/ -static int tcic_set_socket(unsigned int lsock, socket_state_t *state) +static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state) { - u_short psock = socket_table[lsock].psock; + u_short psock = container_of(sock, struct tcic_socket, socket)->psock; u_char reg; u_short scf1, scf2; @@ -811,9 +816,9 @@ static int tcic_set_socket(unsigned int lsock, socket_state_t *state) /*====================================================================*/ -static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io) +static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) { - u_short psock = socket_table[lsock].psock; + u_short psock = container_of(sock, struct tcic_socket, socket)->psock; u_int addr; u_short base, len, ioctl; @@ -848,9 +853,9 @@ static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io) /*====================================================================*/ -static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem) +static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) { - u_short psock = socket_table[lsock].psock; + u_short psock = container_of(sock, struct tcic_socket, socket)->psock; u_short addr, ctl; u_long base, len, mmap; @@ -892,11 +897,11 @@ static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem) /*====================================================================*/ -static void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base) +static void tcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base) { } -static int tcic_init(unsigned int s) +static int tcic_init(struct pcmcia_socket *s) { int i; pccard_io_map io = { 0, 0, 0, 0, 1 }; @@ -915,7 +920,7 @@ static int tcic_init(unsigned int s) return 0; } -static int tcic_suspend(unsigned int sock) +static int tcic_suspend(struct pcmcia_socket *sock) { return tcic_set_socket(sock, &dead_socket); } diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index 353cc02b81819a965775f8387649ea8205eb3881..4e3a3768b22f5dec1b5f242b52e8439e193291cf 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -136,6 +136,26 @@ #ifdef CONFIG_CARDBUS +static int ti_intctl(struct yenta_socket *socket) +{ + u8 new, reg = exca_readb(socket, I365_INTCTL); + + new = reg & ~I365_INTR_ENA; + if (socket->cb_irq) + new |= I365_INTR_ENA; + if (new != reg) + exca_writeb(socket, I365_INTCTL, new); + return 0; +} + +static int ti_init(struct pcmcia_socket *sock) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + yenta_init(sock); + ti_intctl(socket); + return 0; +} + /* * Generic TI init - TI has an extension for the * INTCTL register that sets the PCI CSC interrupt. @@ -148,70 +168,28 @@ * This makes us correctly get PCI CSC interrupt * events. */ -static int ti_open(pci_socket_t *socket) +static int ti_override(struct yenta_socket *socket) { u8 new, reg = exca_readb(socket, I365_INTCTL); new = reg & ~I365_INTR_ENA; if (new != reg) exca_writeb(socket, I365_INTCTL, new); + socket->socket.ss_entry->init = ti_init; return 0; } -static int ti_intctl(pci_socket_t *socket) -{ - u8 new, reg = exca_readb(socket, I365_INTCTL); - - new = reg & ~I365_INTR_ENA; - if (socket->cb_irq) - new |= I365_INTR_ENA; - if (new != reg) - exca_writeb(socket, I365_INTCTL, new); - return 0; -} - -static int ti_init(pci_socket_t *socket) -{ - yenta_init(socket); - ti_intctl(socket); - return 0; -} - -static struct pci_socket_ops ti_ops = { - ti_open, - yenta_close, - ti_init, - yenta_suspend, - yenta_get_status, - yenta_get_socket, - yenta_set_socket, - yenta_set_io_map, - yenta_set_mem_map, - yenta_proc_setup -}; - #define ti_sysctl(socket) ((socket)->private[0]) #define ti_cardctl(socket) ((socket)->private[1]) #define ti_devctl(socket) ((socket)->private[2]) #define ti_diag(socket) ((socket)->private[3]) #define ti_irqmux(socket) ((socket)->private[4]) -static int ti113x_open(pci_socket_t *socket) -{ - ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL); - ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL); - ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL); - ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC); - if (socket->cb_irq) - ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ; - ti_open(socket); - return 0; -} - -static int ti113x_init(pci_socket_t *socket) +static int ti113x_init(struct pcmcia_socket *sock) { - yenta_init(socket); + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + yenta_init(sock); config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket)); config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket)); @@ -220,35 +198,26 @@ static int ti113x_init(pci_socket_t *socket) return 0; } -static struct pci_socket_ops ti113x_ops = { - ti113x_open, - yenta_close, - ti113x_init, - yenta_suspend, - yenta_get_status, - yenta_get_socket, - yenta_set_socket, - yenta_set_io_map, - yenta_set_mem_map, - yenta_proc_setup -}; - - -static int ti1250_open(pci_socket_t *socket) +static int ti113x_override(struct yenta_socket *socket) { - ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC); + ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL); + ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL); + ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL); - ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ); + ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC); if (socket->cb_irq) - ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ; - ti113x_open(socket); + ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ; + ti_override(socket); + socket->socket.ss_entry->init = ti113x_init; return 0; } -static int ti1250_init(pci_socket_t *socket) + +static int ti1250_init(struct pcmcia_socket *sock) { - yenta_init(socket); - ti113x_init(socket); + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + yenta_init(sock); + ti113x_init(sock); ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX); ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */ if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE)) @@ -260,18 +229,17 @@ static int ti1250_init(pci_socket_t *socket) return 0; } -static struct pci_socket_ops ti1250_ops = { - ti1250_open, - yenta_close, - ti1250_init, - yenta_suspend, - yenta_get_status, - yenta_get_socket, - yenta_set_socket, - yenta_set_io_map, - yenta_set_mem_map, - yenta_proc_setup -}; +static int ti1250_override(struct yenta_socket *socket) +{ + ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC); + + ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ); + if (socket->cb_irq) + ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ; + ti113x_override(socket); + socket->socket.ss_entry->init = ti1250_init; + return 0; +} #endif /* CONFIG_CARDBUS */ diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c index 2a3a49d0b72f940d55a88ffea7afb899de4a6292..67eabeb40090943b87a999bd32f123859599ccb1 100644 --- a/drivers/pcmcia/yenta.c +++ b/drivers/pcmcia/yenta.c @@ -1,5 +1,5 @@ /* - * Regular lowlevel cardbus driver ("yenta") + * Regular cardbus driver ("yenta") * * (C) Copyright 1999, 2000 Linus Torvalds * @@ -7,6 +7,8 @@ * Aug 2002: Manfred Spraul <manfred@colorfullife.com> * Dynamically adjust the size of the bridge resource * + * May 2003: Dominik Brodowski <linux@brodo.de> + * Merge pci_socket.c and yenta.c into one file */ #include <linux/init.h> #include <linux/pci.h> @@ -26,6 +28,7 @@ #include "yenta.h" #include "i82365.h" + #if 0 #define DEBUG(x,args...) printk("%s: " x, __FUNCTION__, ##args) #else @@ -41,20 +44,20 @@ * regular memory space ("cb_xxx"), configuration space * ("config_xxx") and compatibility space ("exca_xxxx") */ -static inline u32 cb_readl(pci_socket_t *socket, unsigned reg) +static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg) { u32 val = readl(socket->base + reg); DEBUG("%p %04x %08x\n", socket, reg, val); return val; } -static inline void cb_writel(pci_socket_t *socket, unsigned reg, u32 val) +static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val) { DEBUG("%p %04x %08x\n", socket, reg, val); writel(val, socket->base + reg); } -static inline u8 config_readb(pci_socket_t *socket, unsigned offset) +static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) { u8 val; pci_read_config_byte(socket->dev, offset, &val); @@ -62,7 +65,7 @@ static inline u8 config_readb(pci_socket_t *socket, unsigned offset) return val; } -static inline u16 config_readw(pci_socket_t *socket, unsigned offset) +static inline u16 config_readw(struct yenta_socket *socket, unsigned offset) { u16 val; pci_read_config_word(socket->dev, offset, &val); @@ -70,7 +73,7 @@ static inline u16 config_readw(pci_socket_t *socket, unsigned offset) return val; } -static inline u32 config_readl(pci_socket_t *socket, unsigned offset) +static inline u32 config_readl(struct yenta_socket *socket, unsigned offset) { u32 val; pci_read_config_dword(socket->dev, offset, &val); @@ -78,32 +81,32 @@ static inline u32 config_readl(pci_socket_t *socket, unsigned offset) return val; } -static inline void config_writeb(pci_socket_t *socket, unsigned offset, u8 val) +static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val) { DEBUG("%p %04x %02x\n", socket, offset, val); pci_write_config_byte(socket->dev, offset, val); } -static inline void config_writew(pci_socket_t *socket, unsigned offset, u16 val) +static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val) { DEBUG("%p %04x %04x\n", socket, offset, val); pci_write_config_word(socket->dev, offset, val); } -static inline void config_writel(pci_socket_t *socket, unsigned offset, u32 val) +static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val) { DEBUG("%p %04x %08x\n", socket, offset, val); pci_write_config_dword(socket->dev, offset, val); } -static inline u8 exca_readb(pci_socket_t *socket, unsigned reg) +static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg) { u8 val = readb(socket->base + 0x800 + reg); DEBUG("%p %04x %02x\n", socket, reg, val); return val; } -static inline u8 exca_readw(pci_socket_t *socket, unsigned reg) +static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg) { u16 val; val = readb(socket->base + 0x800 + reg); @@ -112,13 +115,13 @@ static inline u8 exca_readw(pci_socket_t *socket, unsigned reg) return val; } -static inline void exca_writeb(pci_socket_t *socket, unsigned reg, u8 val) +static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val) { DEBUG("%p %04x %02x\n", socket, reg, val); writeb(val, socket->base + 0x800 + reg); } -static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val) +static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) { DEBUG("%p %04x %04x\n", socket, reg, val); writeb(val, socket->base + 0x800 + reg); @@ -129,8 +132,9 @@ static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val) * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend * on what kind of card is inserted.. */ -static int yenta_get_status(pci_socket_t *socket, unsigned int *value) +static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); unsigned int val; u32 state = cb_readl(socket, CB_SOCKET_STATE); @@ -181,8 +185,9 @@ static int yenta_Vpp_power(u32 control) } } -static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state) +static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state) { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); u8 reg; u32 control; @@ -221,7 +226,7 @@ static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state) return 0; } -static void yenta_set_power(pci_socket_t *socket, socket_state_t *state) +static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) { u32 reg = 0; /* CB_SC_STPCLK? */ switch (state->Vcc) { @@ -238,8 +243,9 @@ static void yenta_set_power(pci_socket_t *socket, socket_state_t *state) cb_writel(socket, CB_SOCKET_CONTROL, reg); } -static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state) +static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); u16 bridge; if (state->flags & SS_DEBOUNCED) { @@ -300,8 +306,9 @@ static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state) return 0; } -static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io) +static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); int map; unsigned char ioctl, addr, enable; @@ -333,8 +340,9 @@ static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io) return 0; } -static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) +static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); int map; unsigned char addr, enable; unsigned int start, stop, card_start; @@ -386,12 +394,12 @@ static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) return 0; } -static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base) +static void yenta_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base) { /* Not done yet */ } -static unsigned int yenta_events(pci_socket_t *socket) +static unsigned int yenta_events(struct yenta_socket *socket) { u8 csc; u32 cb_event; @@ -418,7 +426,7 @@ static unsigned int yenta_events(pci_socket_t *socket) static void yenta_bh(void *data) { - pci_socket_t *socket = data; + struct yenta_socket *socket = data; unsigned int events; spin_lock_irq(&socket->event_lock); @@ -432,7 +440,7 @@ static void yenta_bh(void *data) static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int events; - pci_socket_t *socket = (pci_socket_t *) dev_id; + struct yenta_socket *socket = (struct yenta_socket *) dev_id; events = yenta_events(socket); if (events) { @@ -447,7 +455,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void yenta_interrupt_wrapper(unsigned long data) { - pci_socket_t *socket = (pci_socket_t *) data; + struct yenta_socket *socket = (struct yenta_socket *) data; yenta_interrupt(0, (void *)socket, NULL); socket->poll_timer.expires = jiffies + HZ; @@ -465,7 +473,7 @@ static void yenta_interrupt_wrapper(unsigned long data) */ static u32 isa_interrupts = 0x0ef8; -static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask) +static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask) { int i; unsigned long val; @@ -509,7 +517,7 @@ static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask) /* * Set static data that doesn't need re-initializing.. */ -static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask) +static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask) { socket->cap.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; socket->cap.map_size = 0x1000; @@ -520,28 +528,38 @@ static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq); } -static void yenta_clear_maps(pci_socket_t *socket) +static int yenta_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + + *cap = socket->cap; + + return 0; +} + + +static void yenta_clear_maps(struct yenta_socket *socket) { int i; pccard_io_map io = { 0, 0, 0, 0, 1 }; pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; mem.sys_stop = 0x0fff; - yenta_set_socket(socket, &dead_socket); + yenta_set_socket(&socket->socket, &dead_socket); for (i = 0; i < 2; i++) { io.map = i; - yenta_set_io_map(socket, &io); + yenta_set_io_map(&socket->socket, &io); } for (i = 0; i < 5; i++) { mem.map = i; - yenta_set_mem_map(socket, &mem); + yenta_set_mem_map(&socket->socket, &mem); } } /* * Initialize the standard cardbus registers */ -static void yenta_config_init(pci_socket_t *socket) +static void yenta_config_init(struct yenta_socket *socket) { u16 bridge; struct pci_dev *dev = socket->dev; @@ -586,8 +604,9 @@ static void yenta_config_init(pci_socket_t *socket) } /* Called at resume and initialization events */ -static int yenta_init(pci_socket_t *socket) +static int yenta_init(struct pcmcia_socket *sock) { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); yenta_config_init(socket); yenta_clear_maps(socket); @@ -596,9 +615,11 @@ static int yenta_init(pci_socket_t *socket) return 0; } -static int yenta_suspend(pci_socket_t *socket) +static int yenta_suspend(struct pcmcia_socket *sock) { - yenta_set_socket(socket, &dead_socket); + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + + yenta_set_socket(sock, &dead_socket); /* Disable interrupts */ cb_writel(socket, CB_SOCKET_MASK, 0x0); @@ -630,7 +651,7 @@ static int yenta_suspend(pci_socket_t *socket) #define BRIDGE_IO_MAX 256 #define BRIDGE_IO_MIN 32 -static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type) +static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type) { struct pci_bus *bus; struct resource *root, *res; @@ -711,7 +732,7 @@ static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type) /* * Allocate the bridge mappings for the device.. */ -static void yenta_allocate_resources(pci_socket_t *socket) +static void yenta_allocate_resources(struct yenta_socket *socket) { yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH); yenta_allocate_res(socket, 1, IORESOURCE_MEM); @@ -719,10 +740,11 @@ static void yenta_allocate_resources(pci_socket_t *socket) yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */ } + /* * Free the bridge mappings for the device.. */ -static void yenta_free_resources(pci_socket_t *socket) +static void yenta_free_resources(struct yenta_socket *socket) { int i; for (i=0;i<4;i++) { @@ -733,11 +755,15 @@ static void yenta_free_resources(pci_socket_t *socket) res->start = res->end = 0; } } + + /* * Close it down - release our resources and go home.. */ -static void yenta_close(pci_socket_t *sock) +static void yenta_close(struct pci_dev *dev) { + struct yenta_socket *sock = pci_get_drvdata(dev); + /* Disable all events so we don't die in an IRQ storm */ cb_writel(sock, CB_SOCKET_MASK, 0x0); exca_writeb(sock, I365_CSCINT, 0); @@ -750,8 +776,37 @@ static void yenta_close(pci_socket_t *sock) if (sock->base) iounmap(sock->base); yenta_free_resources(sock); + + pcmcia_unregister_socket(&sock->socket); + pci_set_drvdata(dev, NULL); } + +static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + + socket->handler = handler; + socket->info = info; + return 0; +} + + +static struct pccard_operations yenta_socket_operations = { + .owner = THIS_MODULE, + .init = yenta_init, + .suspend = yenta_suspend, + .register_callback = yenta_register_callback, + .inquire_socket = yenta_inquire_socket, + .get_status = yenta_get_status, + .get_socket = yenta_get_socket, + .set_socket = yenta_set_socket, + .set_io_map = yenta_set_io_map, + .set_mem_map = yenta_set_mem_map, + .proc_setup = yenta_proc_setup, +}; + + #include "ti113x.h" #include "ricoh.h" @@ -760,49 +815,62 @@ static void yenta_close(pci_socket_t *sock) * initialization sequences etc details. List them here.. */ #define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y -static struct cardbus_override_struct { +struct cardbus_override_struct { unsigned short vendor; unsigned short device; - struct pci_socket_ops *op; + int (*override) (struct yenta_socket *socket); } cardbus_override[] = { - { PD(TI,1130), &ti113x_ops }, - { PD(TI,1031), &ti_ops }, - { PD(TI,1131), &ti113x_ops }, - { PD(TI,1250), &ti1250_ops }, - { PD(TI,1220), &ti_ops }, - { PD(TI,1221), &ti_ops }, - { PD(TI,1210), &ti_ops }, - { PD(TI,1450), &ti_ops }, - { PD(TI,1225), &ti_ops }, - { PD(TI,1251A), &ti_ops }, - { PD(TI,1211), &ti_ops }, - { PD(TI,1251B), &ti_ops }, - { PD(TI,1410), &ti1250_ops }, - { PD(TI,1420), &ti_ops }, - { PD(TI,4410), &ti_ops }, - { PD(TI,4451), &ti_ops }, - - { PD(RICOH,RL5C465), &ricoh_ops }, - { PD(RICOH,RL5C466), &ricoh_ops }, - { PD(RICOH,RL5C475), &ricoh_ops }, - { PD(RICOH,RL5C476), &ricoh_ops }, - { PD(RICOH,RL5C478), &ricoh_ops } + { PD(TI,1130), &ti113x_override }, + { PD(TI,1031), &ti_override }, + { PD(TI,1131), &ti113x_override }, + { PD(TI,1250), &ti1250_override }, + { PD(TI,1220), &ti_override }, + { PD(TI,1221), &ti_override }, + { PD(TI,1210), &ti_override }, + { PD(TI,1450), &ti_override }, + { PD(TI,1225), &ti_override }, + { PD(TI,1251A), &ti_override }, + { PD(TI,1211), &ti_override }, + { PD(TI,1251B), &ti_override }, + { PD(TI,1410), ti1250_override }, + { PD(TI,1420), &ti_override }, + { PD(TI,4410), &ti_override }, + { PD(TI,4451), &ti_override }, + + { PD(RICOH,RL5C465), &ricoh_override }, + { PD(RICOH,RL5C466), &ricoh_override }, + { PD(RICOH,RL5C475), &ricoh_override }, + { PD(RICOH,RL5C476), &ricoh_override }, + { PD(RICOH,RL5C478), &ricoh_override }, + + { }, /* all zeroes */ }; -#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct)) - - -extern int cardbus_register(struct pci_dev *p_dev); /* * Initialize a cardbus controller. Make sure we have a usable * interrupt, and that we can map the cardbus area. Fill in the * socket information structure.. */ -static int yenta_open(pci_socket_t *socket) +static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id) { - int i; - struct pci_dev *dev = socket->dev; + struct yenta_socket *socket; + struct cardbus_override_struct *d; + + socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); + if (!socket) + return -ENOMEM; + memset(socket, 0, sizeof(*socket)); + + /* prepare pcmcia_socket */ + socket->socket.ss_entry = ¥ta_socket_operations; + socket->socket.dev.dev = &dev->dev; + socket->socket.driver_data = socket; + + /* prepare struct yenta_socket */ + socket->dev = dev; + pci_set_drvdata(dev, socket); + spin_lock_init(&socket->event_lock); /* * Do some basic sanity checking.. @@ -833,16 +901,14 @@ static int yenta_open(pci_socket_t *socket) socket->cb_irq = dev->irq; /* Do we have special options for the device? */ - for (i = 0; i < NR_OVERRIDES; i++) { - struct cardbus_override_struct *d = cardbus_override+i; - if (dev->vendor == d->vendor && dev->device == d->device) { - socket->op = d->op; - if (d->op->open) { - int retval = d->op->open(socket); - if (retval < 0) - return retval; - } + d = cardbus_override; + while (d->override) { + if ((dev->vendor == d->vendor) && (dev->device == d->device)) { + int retval = d->override(socket); + if (retval < 0) + return retval; } + d++; } /* We must finish initialization here */ @@ -864,23 +930,58 @@ static int yenta_open(pci_socket_t *socket) printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); /* Register it with the pcmcia layer.. */ - return cardbus_register(dev); + return pcmcia_register_socket(&socket->socket); } -/* - * Standard plain cardbus - no frills, no extensions - */ -struct pci_socket_ops yenta_operations = { - yenta_open, - yenta_close, - yenta_init, - yenta_suspend, - yenta_get_status, - yenta_get_socket, - yenta_set_socket, - yenta_set_io_map, - yenta_set_mem_map, - yenta_proc_setup + +static int yenta_dev_suspend (struct pci_dev *dev, u32 state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state, 0); +} + + +static int yenta_dev_resume (struct pci_dev *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE); +} + + +static struct pci_device_id yenta_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 */ } }; -EXPORT_SYMBOL(yenta_operations); +MODULE_DEVICE_TABLE(pci, yenta_table); + + +static struct pci_driver yenta_cardbus_driver = { + .name = "yenta_cardbus", + .id_table = yenta_table, + .probe = yenta_probe, + .remove = __devexit_p(yenta_close), + .suspend = yenta_dev_suspend, + .resume = yenta_dev_resume, +}; + + +static int __init yenta_socket_init(void) +{ + return pci_register_driver (¥ta_cardbus_driver); +} + + +static void __exit yenta_socket_exit (void) +{ + pci_unregister_driver (¥ta_cardbus_driver); +} + + +module_init(yenta_socket_init); +module_exit(yenta_socket_exit); + MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/yenta.h b/drivers/pcmcia/yenta.h index c8d61c4093c7b9395cf39e6efacaff94f0502cfb..9c5c0a35df6aabaa6fa723e5f7c37e70e03597bc 100644 --- a/drivers/pcmcia/yenta.h +++ b/drivers/pcmcia/yenta.h @@ -2,7 +2,6 @@ #define __YENTA_H #include <asm/io.h> -#include "pci_socket.h" #define CB_SOCKET_EVENT 0x00 #define CB_CSTSEVENT 0x00000001 /* Card status event */ @@ -96,4 +95,23 @@ */ #define CB_MEM_PAGE(map) (0x40 + (map)) +struct yenta_socket { + struct pci_dev *dev; + int cb_irq, io_irq; + void *base; + void (*handler)(void *, unsigned int); + void *info; + socket_cap_t cap; + spinlock_t event_lock; + unsigned int events; + struct work_struct tq_task; + struct timer_list poll_timer; + + struct pcmcia_socket socket; + + /* A few words of private data for special stuff of overrides... */ + unsigned int private[8]; +}; + + #endif diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index e29dfbb82a991be6d2e8e580f4c0a7ca0a85fde2..4e0f3cf69b354216dd83af3adf5e79d6ca106cb9 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -316,7 +316,7 @@ typedef struct error_info_t { /* Special stuff for binding drivers to sockets */ typedef struct bind_req_t { - socket_t Socket; + struct pcmcia_socket *Socket; u_char Function; dev_info_t *dev_info; } bind_req_t; @@ -325,7 +325,7 @@ typedef struct bind_req_t { #define BIND_FN_ALL 0xff typedef struct mtd_bind_t { - socket_t Socket; + struct pcmcia_socket *Socket; u_int Attributes; u_int CardOffset; dev_info_t *dev_info; diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 2a3917ce1814146d66f73612ab32f443784c7c4c..f69b5a8c4bb74bced63d9b9c3ae910b4c97826ee 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -31,6 +31,8 @@ #define _LINUX_SS_H #include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/bulkmem.h> #include <linux/device.h> /* Definitions for card status flags for GetStatus */ @@ -124,37 +126,138 @@ typedef struct cb_bridge_map { /* * Socket operations. */ +struct pcmcia_socket; + struct pccard_operations { struct module *owner; - int (*init)(unsigned int sock); - int (*suspend)(unsigned int sock); - int (*register_callback)(unsigned int sock, void (*handler)(void *, unsigned int), void * info); - int (*inquire_socket)(unsigned int sock, socket_cap_t *cap); - int (*get_status)(unsigned int sock, u_int *value); - int (*get_socket)(unsigned int sock, socket_state_t *state); - int (*set_socket)(unsigned int sock, socket_state_t *state); - int (*set_io_map)(unsigned int sock, struct pccard_io_map *io); - int (*set_mem_map)(unsigned int sock, struct pccard_mem_map *mem); - void (*proc_setup)(unsigned int sock, struct proc_dir_entry *base); + int (*init)(struct pcmcia_socket *sock); + int (*suspend)(struct pcmcia_socket *sock); + int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info); + int (*inquire_socket)(struct pcmcia_socket *sock, socket_cap_t *cap); + int (*get_status)(struct pcmcia_socket *sock, u_int *value); + int (*get_socket)(struct pcmcia_socket *sock, socket_state_t *state); + int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state); + int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io); + int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem); + void (*proc_setup)(struct pcmcia_socket *sock, struct proc_dir_entry *base); }; /* * Calls to set up low-level "Socket Services" drivers */ +struct pcmcia_socket; struct pcmcia_socket_class_data { unsigned int nsock; /* number of sockets */ unsigned int sock_offset; /* socket # (which is * returned to driver) = sock_offset + (0, 1, .. , (nsock-1) */ struct pccard_operations *ops; /* see above */ - void *s_info; /* socket_info_t */ + struct pcmcia_socket *s_info; struct class_device class_dev; /* generic class structure */ }; +typedef struct erase_busy_t { + eraseq_entry_t *erase; + client_handle_t client; + struct timer_list timeout; + struct erase_busy_t *prev, *next; +} erase_busy_t; + +typedef struct io_window_t { + u_int Attributes; + ioaddr_t BasePort, NumPorts; + ioaddr_t InUse, Config; +} io_window_t; + +#define WINDOW_MAGIC 0xB35C +typedef struct window_t { + u_short magic; + u_short index; + client_handle_t handle; + struct pcmcia_socket *sock; + u_long base; + u_long size; + pccard_mem_map ctl; +} window_t; + +/* Maximum number of IO windows per socket */ +#define MAX_IO_WIN 2 + +/* Maximum number of memory windows per socket */ +#define MAX_WIN 4 + +struct config_t; +struct region_t; + +struct pcmcia_socket { + spinlock_t lock; + struct pccard_operations * ss_entry; + socket_state_t socket; + socket_cap_t cap; + u_int state; + u_short functions; + u_short lock_count; + client_handle_t clients; + u_int real_clients; + pccard_mem_map cis_mem; + u_char *cis_virt; + struct config_t *config; + struct { + u_int AssignedIRQ; + u_int Config; + } irq; + io_window_t io[MAX_IO_WIN]; + window_t win[MAX_WIN]; + struct region_t *c_region, *a_region; + erase_busy_t erase_busy; + struct list_head cis_cache; + u_int fake_cis_len; + char *fake_cis; + + struct list_head socket_list; + + /* deprecated */ + unsigned int sock; /* socket number */ + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc; +#endif + + /* state thread */ + struct semaphore skt_sem; /* protects socket h/w state */ + + struct task_struct *thread; + struct completion thread_done; + wait_queue_head_t thread_wait; + spinlock_t thread_lock; /* protects thread_events */ + unsigned int thread_events; + + /* pcmcia (16-bit) */ + struct pcmcia_bus_socket *pcmcia; + + /* cardbus (32-bit) */ +#ifdef CONFIG_CARDBUS + struct resource * cb_cis_res; + u_char *cb_cis_virt; +#endif + + /* socket device */ + struct class_device dev; + void *driver_data; /* data internal to the socket driver */ + +}; + +struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr); + + + +extern int pcmcia_register_socket(struct pcmcia_socket *socket); +extern void pcmcia_unregister_socket(struct pcmcia_socket *socket); + extern struct class pcmcia_socket_class; /* socket drivers are expected to use these callbacks in their .drv struct */ -extern int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level); -extern int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level); +extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level); +extern int pcmcia_socket_dev_resume(struct device *dev, u32 level); #endif /* _LINUX_SS_H */