upgrade wireless-tools and iproute2
[openwrt.git] / package / linux / kernel-source / drivers / pcmcia / bcm4710_generic.c
1 /*
2  *
3  * bcm47xx pcmcia driver
4  *
5  * Copyright 2004, Broadcom Corporation
6  * All Rights Reserved.
7  * 
8  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
9  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
10  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
11  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12  *
13  * Based on sa1100_generic.c from www.handhelds.org,
14  *      and au1000_generic.c from oss.sgi.com.
15  *
16  * $Id$
17  */
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/config.h>
21 #include <linux/delay.h>
22 #include <linux/ioport.h>
23 #include <linux/kernel.h>
24 #include <linux/tqueue.h>
25 #include <linux/timer.h>
26 #include <linux/mm.h>
27 #include <linux/proc_fs.h>
28 #include <linux/version.h>
29 #include <linux/types.h>
30 #include <linux/vmalloc.h>
31
32 #include <pcmcia/version.h>
33 #include <pcmcia/cs_types.h>
34 #include <pcmcia/cs.h>
35 #include <pcmcia/ss.h>
36 #include <pcmcia/bulkmem.h>
37 #include <pcmcia/cistpl.h>
38 #include <pcmcia/bus_ops.h>
39 #include "cs_internal.h"
40
41 #include <asm/io.h>
42 #include <asm/irq.h>
43 #include <asm/system.h>
44
45 #include <typedefs.h>
46 #include <bcm4710.h>
47 #include <sbextif.h>
48
49 #include "bcm4710pcmcia.h"
50
51 #ifdef PCMCIA_DEBUG
52 static int pc_debug = PCMCIA_DEBUG;
53 #endif
54
55 MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm47xx Socket Controller");
56
57 /* This structure maintains housekeeping state for each socket, such
58  * as the last known values of the card detect pins, or the Card Services
59  * callback value associated with the socket:
60  */
61 static struct bcm47xx_pcmcia_socket *pcmcia_socket;
62 static int socket_count;
63
64
65 /* Returned by the low-level PCMCIA interface: */
66 static struct pcmcia_low_level *pcmcia_low_level;
67
68 /* Event poll timer structure */
69 static struct timer_list poll_timer;
70
71
72 /* Prototypes for routines which are used internally: */
73
74 static int  bcm47xx_pcmcia_driver_init(void);
75 static void bcm47xx_pcmcia_driver_shutdown(void);
76 static void bcm47xx_pcmcia_task_handler(void *data);
77 static void bcm47xx_pcmcia_poll_event(unsigned long data);
78 static void bcm47xx_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs);
79 static struct tq_struct bcm47xx_pcmcia_task;
80
81 #ifdef CONFIG_PROC_FS
82 static int bcm47xx_pcmcia_proc_status(char *buf, char **start, 
83                 off_t pos, int count, int *eof, void *data);
84 #endif
85
86
87 /* Prototypes for operations which are exported to the
88  * in-kernel PCMCIA core:
89  */
90
91 static int bcm47xx_pcmcia_init(unsigned int sock);
92 static int bcm47xx_pcmcia_suspend(unsigned int sock);
93 static int bcm47xx_pcmcia_register_callback(unsigned int sock, 
94                 void (*handler)(void *, unsigned int), void *info);
95 static int bcm47xx_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap);
96 static int bcm47xx_pcmcia_get_status(unsigned int sock, u_int *value);
97 static int bcm47xx_pcmcia_get_socket(unsigned int sock, socket_state_t *state);
98 static int bcm47xx_pcmcia_set_socket(unsigned int sock, socket_state_t *state);
99 static int bcm47xx_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *io);
100 static int bcm47xx_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *io);
101 static int bcm47xx_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *mem);
102 static int bcm47xx_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *mem);
103 #ifdef CONFIG_PROC_FS
104 static void bcm47xx_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base);
105 #endif
106
107 static struct pccard_operations bcm47xx_pcmcia_operations = {
108         bcm47xx_pcmcia_init,
109         bcm47xx_pcmcia_suspend,
110         bcm47xx_pcmcia_register_callback,
111         bcm47xx_pcmcia_inquire_socket,
112         bcm47xx_pcmcia_get_status,
113         bcm47xx_pcmcia_get_socket,
114         bcm47xx_pcmcia_set_socket,
115         bcm47xx_pcmcia_get_io_map,
116         bcm47xx_pcmcia_set_io_map,
117         bcm47xx_pcmcia_get_mem_map,
118         bcm47xx_pcmcia_set_mem_map,
119 #ifdef CONFIG_PROC_FS
120         bcm47xx_pcmcia_proc_setup
121 #endif
122 };
123
124
125 /*
126  * bcm47xx_pcmcia_driver_init()
127  *
128  * This routine performs a basic sanity check to ensure that this
129  * kernel has been built with the appropriate board-specific low-level
130  * PCMCIA support, performs low-level PCMCIA initialization, registers
131  * this socket driver with Card Services, and then spawns the daemon
132  * thread which is the real workhorse of the socket driver.
133  *
134  * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
135  * on the low-level kernel interface.
136  *
137  * Returns: 0 on success, -1 on error
138  */
139 static int __init bcm47xx_pcmcia_driver_init(void)
140 {
141         servinfo_t info;
142         struct pcmcia_init pcmcia_init;
143         struct pcmcia_state state;
144         unsigned int i;
145         unsigned long tmp;
146
147
148         printk("\nBCM47XX PCMCIA (CS release %s)\n", CS_RELEASE);
149
150         CardServices(GetCardServicesInfo, &info);
151
152         if (info.Revision != CS_RELEASE_CODE) {
153                 printk(KERN_ERR "Card Services release codes do not match\n");
154                 return -1;
155         }
156
157 #ifdef CONFIG_BCM4710
158         pcmcia_low_level=&bcm4710_pcmcia_ops;
159 #else
160 #error Unsupported Broadcom BCM47XX board.
161 #endif
162
163         pcmcia_init.handler=bcm47xx_pcmcia_interrupt;
164
165         if ((socket_count = pcmcia_low_level->init(&pcmcia_init)) < 0) {
166                 printk(KERN_ERR "Unable to initialize PCMCIA service.\n");
167                 return -EIO;
168         } else {
169                 printk("\t%d PCMCIA sockets initialized.\n", socket_count);
170         }
171
172         pcmcia_socket = 
173                 kmalloc(sizeof(struct bcm47xx_pcmcia_socket) * socket_count, 
174                                 GFP_KERNEL);
175         memset(pcmcia_socket, 0, 
176                         sizeof(struct bcm47xx_pcmcia_socket) * socket_count);
177         if (!pcmcia_socket) {
178                 printk(KERN_ERR "Card Services can't get memory \n");
179                 return -1;
180         }
181                         
182         for (i = 0; i < socket_count; i++) {
183                 if (pcmcia_low_level->socket_state(i, &state) < 0) {
184                         printk(KERN_ERR "Unable to get PCMCIA status\n");
185                         return -EIO;
186                 }
187                 pcmcia_socket[i].k_state = state;
188                 pcmcia_socket[i].cs_state.csc_mask = SS_DETECT;
189                 
190                 if (i == 0) {
191                         pcmcia_socket[i].virt_io =
192                                 (unsigned long)ioremap_nocache(EXTIF_PCMCIA_IOBASE(BCM4710_EXTIF), 0x1000);
193                         /* Substract ioport base which gets added by in/out */
194                         pcmcia_socket[i].virt_io -= mips_io_port_base;
195                         pcmcia_socket[i].phys_attr =
196                                 (unsigned long)EXTIF_PCMCIA_CFGBASE(BCM4710_EXTIF);
197                         pcmcia_socket[i].phys_mem =
198                                 (unsigned long)EXTIF_PCMCIA_MEMBASE(BCM4710_EXTIF);
199                 } else  {
200                         printk(KERN_ERR "bcm4710: socket 1 not supported\n");
201                         return 1;
202                 }
203         }
204
205         /* Only advertise as many sockets as we can detect: */
206         if (register_ss_entry(socket_count, &bcm47xx_pcmcia_operations) < 0) {
207                 printk(KERN_ERR "Unable to register socket service routine\n");
208                 return -ENXIO;
209         }
210
211         /* Start the event poll timer.  
212          * It will reschedule by itself afterwards. 
213          */
214         bcm47xx_pcmcia_poll_event(0);
215
216         DEBUG(1, "bcm4710: initialization complete\n");
217         return 0;
218
219 }
220
221 module_init(bcm47xx_pcmcia_driver_init);
222
223
224 /*
225  * bcm47xx_pcmcia_driver_shutdown()
226  *
227  * Invokes the low-level kernel service to free IRQs associated with this
228  * socket controller and reset GPIO edge detection.
229  */
230 static void __exit bcm47xx_pcmcia_driver_shutdown(void)
231 {
232         int i;
233
234         del_timer_sync(&poll_timer);
235         unregister_ss_entry(&bcm47xx_pcmcia_operations);
236         pcmcia_low_level->shutdown();
237         flush_scheduled_tasks();
238         for (i = 0; i < socket_count; i++) {
239                 if (pcmcia_socket[i].virt_io) 
240                         iounmap((void *)pcmcia_socket[i].virt_io);
241                 if (pcmcia_socket[i].phys_attr) 
242                         iounmap((void *)pcmcia_socket[i].phys_attr);
243                 if (pcmcia_socket[i].phys_mem) 
244                         iounmap((void *)pcmcia_socket[i].phys_mem);
245         }
246         DEBUG(1, "bcm4710: shutdown complete\n");
247 }
248
249 module_exit(bcm47xx_pcmcia_driver_shutdown);
250
251 /*
252  * bcm47xx_pcmcia_init()
253  * We perform all of the interesting initialization tasks in 
254  * bcm47xx_pcmcia_driver_init().
255  *
256  * Returns: 0
257  */
258 static int bcm47xx_pcmcia_init(unsigned int sock)
259 {
260         DEBUG(1, "%s(): initializing socket %u\n", __FUNCTION__, sock);
261
262         return 0;
263 }
264
265 /*
266  * bcm47xx_pcmcia_suspend()
267  *
268  * We don't currently perform any actions on a suspend.
269  *
270  * Returns: 0
271  */
272 static int bcm47xx_pcmcia_suspend(unsigned int sock)
273 {
274         DEBUG(1, "%s(): suspending socket %u\n", __FUNCTION__, sock);
275
276         return 0;
277 }
278
279
280 /*
281  * bcm47xx_pcmcia_events()
282  *
283  * Helper routine to generate a Card Services event mask based on
284  * state information obtained from the kernel low-level PCMCIA layer
285  * in a recent (and previous) sampling. Updates `prev_state'.
286  *
287  * Returns: an event mask for the given socket state.
288  */
289 static inline unsigned 
290 bcm47xx_pcmcia_events(struct pcmcia_state *state, 
291                 struct pcmcia_state *prev_state, 
292                 unsigned int mask, unsigned int flags)
293 {
294         unsigned int events=0;
295
296         if (state->bvd1 != prev_state->bvd1) {
297
298                 DEBUG(3, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1);
299
300                 events |= mask & (flags & SS_IOCARD) ? SS_STSCHG : SS_BATDEAD;
301         }
302
303         if (state->bvd2 != prev_state->bvd2) {
304
305                 DEBUG(3, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2);
306
307                 events |= mask & (flags & SS_IOCARD) ? 0 : SS_BATWARN;
308         }
309
310         if (state->detect != prev_state->detect) {
311
312                 DEBUG(3, "%s(): card detect value %u\n", __FUNCTION__, state->detect);
313
314                 events |= mask & SS_DETECT;
315         }
316
317
318         if (state->ready != prev_state->ready) {
319
320                 DEBUG(3, "%s(): card ready value %u\n", __FUNCTION__, state->ready);
321
322                 events |= mask & ((flags & SS_IOCARD) ? 0 : SS_READY);
323         }
324
325         if (events != 0) {
326                 DEBUG(2, "events: %s%s%s%s%s\n",
327                       (events & SS_DETECT) ? "DETECT " : "",
328                       (events & SS_READY) ? "READY " : "",
329                       (events & SS_BATDEAD) ? "BATDEAD " : "",
330                       (events & SS_BATWARN) ? "BATWARN " : "",
331                       (events & SS_STSCHG) ? "STSCHG " : "");
332         }
333
334         *prev_state=*state;
335         return events;
336 }
337
338
339 /* 
340  * bcm47xx_pcmcia_task_handler()
341  *
342  * Processes serviceable socket events using the "eventd" thread context.
343  *
344  * Event processing (specifically, the invocation of the Card Services event
345  * callback) occurs in this thread rather than in the actual interrupt
346  * handler due to the use of scheduling operations in the PCMCIA core.
347  */
348 static void bcm47xx_pcmcia_task_handler(void *data) 
349 {
350         struct pcmcia_state state;
351         int i, events, irq_status;
352
353         DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
354
355         for (i = 0; i < socket_count; i++)  {
356                 if ((irq_status = pcmcia_low_level->socket_state(i, &state)) < 0)
357                         printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n");
358
359                 events = bcm47xx_pcmcia_events(&state, 
360                                                &pcmcia_socket[i].k_state, 
361                                                pcmcia_socket[i].cs_state.csc_mask, 
362                                                pcmcia_socket[i].cs_state.flags);
363
364                 if (pcmcia_socket[i].handler != NULL) {
365                         pcmcia_socket[i].handler(pcmcia_socket[i].handler_info,
366                                                  events);
367                 }
368         }
369 }
370
371 static struct tq_struct bcm47xx_pcmcia_task = {
372         routine: bcm47xx_pcmcia_task_handler
373 };
374
375
376 /*
377  * bcm47xx_pcmcia_poll_event()
378  *
379  * Let's poll for events in addition to IRQs since IRQ only is unreliable...
380  */
381 static void bcm47xx_pcmcia_poll_event(unsigned long dummy)
382 {
383         DEBUG(4, "%s(): polling for events\n", __FUNCTION__);
384
385         poll_timer.function = bcm47xx_pcmcia_poll_event;
386         poll_timer.expires = jiffies + BCM47XX_PCMCIA_POLL_PERIOD;
387         add_timer(&poll_timer);
388         schedule_task(&bcm47xx_pcmcia_task);
389 }
390
391
392 /* 
393  * bcm47xx_pcmcia_interrupt()
394  *
395  * Service routine for socket driver interrupts (requested by the
396  * low-level PCMCIA init() operation via bcm47xx_pcmcia_thread()).
397  *
398  * The actual interrupt-servicing work is performed by
399  * bcm47xx_pcmcia_task(), largely because the Card Services event-
400  * handling code performs scheduling operations which cannot be
401  * executed from within an interrupt context.
402  */
403 static void 
404 bcm47xx_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
405 {
406         DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
407         schedule_task(&bcm47xx_pcmcia_task);
408 }
409
410
411 /*
412  * bcm47xx_pcmcia_register_callback()
413  *
414  * Implements the register_callback() operation for the in-kernel
415  * PCMCIA service (formerly SS_RegisterCallback in Card Services). If 
416  * the function pointer `handler' is not NULL, remember the callback 
417  * location in the state for `sock', and increment the usage counter 
418  * for the driver module. (The callback is invoked from the interrupt
419  * service routine, bcm47xx_pcmcia_interrupt(), to notify Card Services
420  * of interesting events.) Otherwise, clear the callback pointer in the
421  * socket state and decrement the module usage count.
422  *
423  * Returns: 0
424  */
425 static int 
426 bcm47xx_pcmcia_register_callback(unsigned int sock, 
427                 void (*handler)(void *, unsigned int), void *info)
428 {
429         if (handler == NULL) {
430                 pcmcia_socket[sock].handler = NULL;
431                 MOD_DEC_USE_COUNT;
432         } else {
433                 MOD_INC_USE_COUNT;
434                 pcmcia_socket[sock].handler = handler;
435                 pcmcia_socket[sock].handler_info = info;
436         }
437         return 0;
438 }
439
440
441 /*
442  * bcm47xx_pcmcia_inquire_socket()
443  *
444  * Implements the inquire_socket() operation for the in-kernel PCMCIA
445  * service (formerly SS_InquireSocket in Card Services). Of note is
446  * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of
447  * `cap' to "trick" Card Services into tolerating large "I/O memory" 
448  * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory
449  * resource database check. (Mapped memory is set up within the socket
450  * driver itself.)
451  *
452  * In conjunction with the STATIC_MAP capability is a new field,
453  * `io_offset', recommended by David Hinds. Rather than go through
454  * the SetIOMap interface (which is not quite suited for communicating
455  * window locations up from the socket driver), we just pass up
456  * an offset which is applied to client-requested base I/O addresses
457  * in alloc_io_space().
458  *
459  * Returns: 0 on success, -1 if no pin has been configured for `sock'
460  */
461 static int
462 bcm47xx_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap)
463 {
464         struct pcmcia_irq_info irq_info;
465
466         if (sock >= socket_count) {
467                 printk(KERN_ERR "bcm47xx: socket %u not configured\n", sock);
468                 return -1;
469         }
470
471         /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
472          *   force_low argument to validate_mem() in rsrc_mgr.c -- since in
473          *   general, the mapped * addresses of the PCMCIA memory regions
474          *   will not be within 0xffff, setting force_low would be
475          *   undesirable.
476          *
477          * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
478          *   resource database; we instead pass up physical address ranges
479          *   and allow other parts of Card Services to deal with remapping.
480          *
481          * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
482          *   not 32-bit CardBus devices.
483          */
484         cap->features = (SS_CAP_PAGE_REGS  | SS_CAP_STATIC_MAP | SS_CAP_PCCARD);
485
486         irq_info.sock = sock;
487         irq_info.irq = -1;
488
489         if (pcmcia_low_level->get_irq_info(&irq_info) < 0) {
490                 printk(KERN_ERR "Error obtaining IRQ info socket %u\n", sock);
491                 return -1;
492         }
493
494         cap->irq_mask = 0;
495         cap->map_size = PAGE_SIZE;
496         cap->pci_irq = irq_info.irq;
497         cap->io_offset = pcmcia_socket[sock].virt_io;
498
499         return 0;
500 }
501
502
503 /*
504  * bcm47xx_pcmcia_get_status()
505  *
506  * Implements the get_status() operation for the in-kernel PCMCIA
507  * service (formerly SS_GetStatus in Card Services). Essentially just
508  * fills in bits in `status' according to internal driver state or
509  * the value of the voltage detect chipselect register.
510  *
511  * As a debugging note, during card startup, the PCMCIA core issues
512  * three set_socket() commands in a row the first with RESET deasserted,
513  * the second with RESET asserted, and the last with RESET deasserted
514  * again. Following the third set_socket(), a get_status() command will
515  * be issued. The kernel is looking for the SS_READY flag (see
516  * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
517  *
518  * Returns: 0
519  */
520 static int 
521 bcm47xx_pcmcia_get_status(unsigned int sock, unsigned int *status)
522 {
523         struct pcmcia_state state;
524
525
526         if ((pcmcia_low_level->socket_state(sock, &state)) < 0) {
527                 printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
528                 return -1;
529         }
530
531         pcmcia_socket[sock].k_state = state;
532
533         *status = state.detect ? SS_DETECT : 0;
534
535         *status |= state.ready ? SS_READY : 0;
536
537         /* The power status of individual sockets is not available
538          * explicitly from the hardware, so we just remember the state
539          * and regurgitate it upon request:
540          */
541         *status |= pcmcia_socket[sock].cs_state.Vcc ? SS_POWERON : 0;
542
543         if (pcmcia_socket[sock].cs_state.flags & SS_IOCARD)
544                 *status |= state.bvd1 ? SS_STSCHG : 0;
545         else {
546                 if (state.bvd1 == 0)
547                         *status |= SS_BATDEAD;
548                 else if (state.bvd2 == 0)
549                         *status |= SS_BATWARN;
550         }
551
552         *status |= state.vs_3v ? SS_3VCARD : 0;
553
554         *status |= state.vs_Xv ? SS_XVCARD : 0;
555
556         DEBUG(2, "\tstatus: %s%s%s%s%s%s%s%s\n",
557               (*status&SS_DETECT)?"DETECT ":"",
558               (*status&SS_READY)?"READY ":"", 
559               (*status&SS_BATDEAD)?"BATDEAD ":"",
560               (*status&SS_BATWARN)?"BATWARN ":"",
561               (*status&SS_POWERON)?"POWERON ":"",
562               (*status&SS_STSCHG)?"STSCHG ":"",
563               (*status&SS_3VCARD)?"3VCARD ":"",
564               (*status&SS_XVCARD)?"XVCARD ":"");
565
566         return 0;
567 }
568
569
570 /*
571  * bcm47xx_pcmcia_get_socket()
572  *
573  * Implements the get_socket() operation for the in-kernel PCMCIA
574  * service (formerly SS_GetSocket in Card Services). Not a very 
575  * exciting routine.
576  *
577  * Returns: 0
578  */
579 static int 
580 bcm47xx_pcmcia_get_socket(unsigned int sock, socket_state_t *state)
581 {
582         DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
583
584         /* This information was given to us in an earlier call to set_socket(),
585          * so we're just regurgitating it here:
586          */
587         *state = pcmcia_socket[sock].cs_state;
588         return 0;
589 }
590
591
592 /*
593  * bcm47xx_pcmcia_set_socket()
594  *
595  * Implements the set_socket() operation for the in-kernel PCMCIA
596  * service (formerly SS_SetSocket in Card Services). We more or
597  * less punt all of this work and let the kernel handle the details
598  * of power configuration, reset, &c. We also record the value of
599  * `state' in order to regurgitate it to the PCMCIA core later.
600  *
601  * Returns: 0
602  */
603 static int 
604 bcm47xx_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
605 {
606         struct pcmcia_configure configure;
607
608         DEBUG(2, "\tmask:  %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
609               "\tVcc %d  Vpp %d  irq %d\n",
610               (state->csc_mask == 0) ? "<NONE>" : "",
611               (state->csc_mask & SS_DETECT) ? "DETECT " : "",
612               (state->csc_mask & SS_READY) ? "READY " : "",
613               (state->csc_mask & SS_BATDEAD) ? "BATDEAD " : "",
614               (state->csc_mask & SS_BATWARN) ? "BATWARN " : "",
615               (state->csc_mask & SS_STSCHG) ? "STSCHG " : "",
616               (state->flags == 0) ? "<NONE>" : "",
617               (state->flags & SS_PWR_AUTO) ? "PWR_AUTO " : "",
618               (state->flags & SS_IOCARD) ? "IOCARD " : "",
619               (state->flags & SS_RESET) ? "RESET " : "",
620               (state->flags & SS_SPKR_ENA) ? "SPKR_ENA " : "",
621               (state->flags & SS_OUTPUT_ENA) ? "OUTPUT_ENA " : "",
622               state->Vcc, state->Vpp, state->io_irq);
623
624         configure.sock = sock;
625         configure.vcc = state->Vcc;
626         configure.vpp = state->Vpp;
627         configure.output = (state->flags & SS_OUTPUT_ENA) ? 1 : 0;
628         configure.speaker = (state->flags & SS_SPKR_ENA) ? 1 : 0;
629         configure.reset = (state->flags & SS_RESET) ? 1 : 0;
630
631         if (pcmcia_low_level->configure_socket(&configure) < 0) {
632                 printk(KERN_ERR "Unable to configure socket %u\n", sock);
633                 return -1;
634         }
635
636         pcmcia_socket[sock].cs_state = *state;
637         return 0;
638 }
639
640
641 /*
642  * bcm47xx_pcmcia_get_io_map()
643  *
644  * Implements the get_io_map() operation for the in-kernel PCMCIA
645  * service (formerly SS_GetIOMap in Card Services). Just returns an
646  * I/O map descriptor which was assigned earlier by a set_io_map().
647  *
648  * Returns: 0 on success, -1 if the map index was out of range
649  */
650 static int 
651 bcm47xx_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map)
652 {
653         DEBUG(2, "bcm47xx_pcmcia_get_io_map: sock %d\n", sock);
654
655         if (map->map >= MAX_IO_WIN) {
656                 printk(KERN_ERR "%s(): map (%d) out of range\n", 
657                        __FUNCTION__, map->map);
658                 return -1;
659         }
660
661         *map = pcmcia_socket[sock].io_map[map->map];
662         return 0;
663 }
664
665
666 /*
667  * bcm47xx_pcmcia_set_io_map()
668  *
669  * Implements the set_io_map() operation for the in-kernel PCMCIA
670  * service (formerly SS_SetIOMap in Card Services). We configure
671  * the map speed as requested, but override the address ranges
672  * supplied by Card Services.
673  *
674  * Returns: 0 on success, -1 on error
675  */
676 int 
677 bcm47xx_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
678 {
679         unsigned int speed;
680         unsigned long start;
681
682         DEBUG(2, "\tmap %u  speed %u\n\tstart 0x%08lx  stop 0x%08lx\n"
683               "\tflags: %s%s%s%s%s%s%s%s\n",
684               map->map, map->speed, map->start, map->stop,
685               (map->flags == 0) ? "<NONE>" : "",
686               (map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
687               (map->flags & MAP_16BIT) ? "16BIT " : "",
688               (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
689               (map->flags & MAP_0WS) ? "0WS " : "",
690               (map->flags & MAP_WRPROT) ? "WRPROT " : "",
691               (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "",
692               (map->flags & MAP_PREFETCH) ? "PREFETCH " : "");
693
694         if (map->map >= MAX_IO_WIN) {
695                 printk(KERN_ERR "%s(): map (%d) out of range\n", 
696                                 __FUNCTION__, map->map);
697                 return -1;
698         }
699
700         if (map->flags & MAP_ACTIVE) {
701                 speed = (map->speed > 0) ? map->speed : BCM47XX_PCMCIA_IO_SPEED;
702                 pcmcia_socket[sock].speed_io = speed;
703         }
704
705         start = map->start;
706
707         if (map->stop == 1) {
708                 map->stop = PAGE_SIZE - 1;
709         }
710
711         map->start = pcmcia_socket[sock].virt_io;
712         map->stop = map->start + (map->stop - start);
713         pcmcia_socket[sock].io_map[map->map] = *map;
714         DEBUG(2, "set_io_map %d start %x stop %x\n", 
715               map->map, map->start, map->stop);
716         return 0;
717 }
718
719
720 /*
721  * bcm47xx_pcmcia_get_mem_map()
722  *
723  * Implements the get_mem_map() operation for the in-kernel PCMCIA
724  * service (formerly SS_GetMemMap in Card Services). Just returns a
725  *  memory map descriptor which was assigned earlier by a
726  *  set_mem_map() request.
727  *
728  * Returns: 0 on success, -1 if the map index was out of range
729  */
730 static int 
731 bcm47xx_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map)
732 {
733         DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
734
735         if (map->map >= MAX_WIN) {
736                 printk(KERN_ERR "%s(): map (%d) out of range\n", 
737                        __FUNCTION__, map->map);
738                 return -1;
739         }
740
741         *map = pcmcia_socket[sock].mem_map[map->map];
742         return 0;
743 }
744
745
746 /*
747  * bcm47xx_pcmcia_set_mem_map()
748  *
749  * Implements the set_mem_map() operation for the in-kernel PCMCIA
750  * service (formerly SS_SetMemMap in Card Services). We configure
751  * the map speed as requested, but override the address ranges
752  * supplied by Card Services.
753  *
754  * Returns: 0 on success, -1 on error
755  */
756 static int 
757 bcm47xx_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
758 {
759         unsigned int speed;
760         unsigned long start;
761         u_long flags;
762
763         if (map->map >= MAX_WIN) {
764                 printk(KERN_ERR "%s(): map (%d) out of range\n", 
765                        __FUNCTION__, map->map);
766                 return -1;
767         }
768
769         DEBUG(2, "\tmap %u  speed %u\n\tsys_start  %#lx\n"
770               "\tsys_stop   %#lx\n\tcard_start %#x\n"
771               "\tflags: %s%s%s%s%s%s%s%s\n",
772               map->map, map->speed, map->sys_start, map->sys_stop,
773               map->card_start, (map->flags == 0) ? "<NONE>" : "",
774               (map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
775               (map->flags & MAP_16BIT) ? "16BIT " : "",
776               (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
777               (map->flags & MAP_0WS) ? "0WS " : "",
778               (map->flags & MAP_WRPROT) ? "WRPROT " : "",
779               (map->flags & MAP_ATTRIB) ? "ATTRIB " : "",
780               (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "");
781
782         if (map->flags & MAP_ACTIVE) {
783                 /* When clients issue RequestMap, the access speed is not always
784                  * properly configured:
785                  */
786                 speed = (map->speed > 0) ? map->speed : BCM47XX_PCMCIA_MEM_SPEED;
787
788                 /* TBD */
789                 if (map->flags & MAP_ATTRIB) {
790                         pcmcia_socket[sock].speed_attr = speed;
791                 } else {
792                         pcmcia_socket[sock].speed_mem = speed;
793                 }
794         }
795
796         save_flags(flags);
797         cli();
798         start = map->sys_start;
799
800         if (map->sys_stop == 0)
801                 map->sys_stop = PAGE_SIZE - 1;
802
803         if (map->flags & MAP_ATTRIB) {
804                 map->sys_start = pcmcia_socket[sock].phys_attr + 
805                         map->card_start;
806         } else {
807                 map->sys_start = pcmcia_socket[sock].phys_mem + 
808                         map->card_start;
809         }
810
811         map->sys_stop = map->sys_start + (map->sys_stop - start);
812         pcmcia_socket[sock].mem_map[map->map] = *map;
813         restore_flags(flags);
814         DEBUG(2, "set_mem_map %d start %x stop %x card_start %x\n", 
815                         map->map, map->sys_start, map->sys_stop, 
816                         map->card_start);
817         return 0;
818 }
819
820
821 #if defined(CONFIG_PROC_FS)
822
823 /*
824  * bcm47xx_pcmcia_proc_setup()
825  *
826  * Implements the proc_setup() operation for the in-kernel PCMCIA
827  * service (formerly SS_ProcSetup in Card Services).
828  *
829  * Returns: 0 on success, -1 on error
830  */
831 static void 
832 bcm47xx_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
833 {
834         struct proc_dir_entry *entry;
835
836         if ((entry = create_proc_entry("status", 0, base)) == NULL) {
837                 printk(KERN_ERR "Unable to install \"status\" procfs entry\n");
838                 return;
839         }
840
841         entry->read_proc = bcm47xx_pcmcia_proc_status;
842         entry->data = (void *)sock;
843 }
844
845
846 /*
847  * bcm47xx_pcmcia_proc_status()
848  *
849  * Implements the /proc/bus/pccard/??/status file.
850  *
851  * Returns: the number of characters added to the buffer
852  */
853 static int 
854 bcm47xx_pcmcia_proc_status(char *buf, char **start, off_t pos, 
855                            int count, int *eof, void *data)
856 {
857         char *p = buf;
858         unsigned int sock = (unsigned int)data;
859
860         p += sprintf(p, "k_flags  : %s%s%s%s%s%s%s\n", 
861                      pcmcia_socket[sock].k_state.detect ? "detect " : "",
862                      pcmcia_socket[sock].k_state.ready ? "ready " : "",
863                      pcmcia_socket[sock].k_state.bvd1 ? "bvd1 " : "",
864                      pcmcia_socket[sock].k_state.bvd2 ? "bvd2 " : "",
865                      pcmcia_socket[sock].k_state.wrprot ? "wrprot " : "",
866                      pcmcia_socket[sock].k_state.vs_3v ? "vs_3v " : "",
867                      pcmcia_socket[sock].k_state.vs_Xv ? "vs_Xv " : "");
868
869         p += sprintf(p, "status   : %s%s%s%s%s%s%s%s%s\n",
870                      pcmcia_socket[sock].k_state.detect ? "SS_DETECT " : "",
871                      pcmcia_socket[sock].k_state.ready ? "SS_READY " : "",
872                      pcmcia_socket[sock].cs_state.Vcc ? "SS_POWERON " : "",
873                      pcmcia_socket[sock].cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "",
874                      (pcmcia_socket[sock].cs_state.flags & SS_IOCARD &&
875                       pcmcia_socket[sock].k_state.bvd1) ? "SS_STSCHG " : "",
876                      ((pcmcia_socket[sock].cs_state.flags & SS_IOCARD) == 0 &&
877                       (pcmcia_socket[sock].k_state.bvd1 == 0)) ? "SS_BATDEAD " : "",
878                      ((pcmcia_socket[sock].cs_state.flags & SS_IOCARD) == 0 &&
879                       (pcmcia_socket[sock].k_state.bvd2 == 0)) ? "SS_BATWARN " : "",
880                      pcmcia_socket[sock].k_state.vs_3v ? "SS_3VCARD " : "",
881                      pcmcia_socket[sock].k_state.vs_Xv ? "SS_XVCARD " : "");
882
883         p += sprintf(p, "mask     : %s%s%s%s%s\n",
884                      pcmcia_socket[sock].cs_state.csc_mask & SS_DETECT ? "SS_DETECT " : "",
885                      pcmcia_socket[sock].cs_state.csc_mask & SS_READY ? "SS_READY " : "",
886                      pcmcia_socket[sock].cs_state.csc_mask & SS_BATDEAD ? "SS_BATDEAD " : "",
887                      pcmcia_socket[sock].cs_state.csc_mask & SS_BATWARN ? "SS_BATWARN " : "",
888                      pcmcia_socket[sock].cs_state.csc_mask & SS_STSCHG ? "SS_STSCHG " : "");
889
890         p += sprintf(p, "cs_flags : %s%s%s%s%s\n",
891                      pcmcia_socket[sock].cs_state.flags & SS_PWR_AUTO ?
892                         "SS_PWR_AUTO " : "",
893                      pcmcia_socket[sock].cs_state.flags & SS_IOCARD ?
894                         "SS_IOCARD " : "",
895                      pcmcia_socket[sock].cs_state.flags & SS_RESET ?
896                         "SS_RESET " : "",
897                      pcmcia_socket[sock].cs_state.flags & SS_SPKR_ENA ?
898                         "SS_SPKR_ENA " : "",
899                      pcmcia_socket[sock].cs_state.flags & SS_OUTPUT_ENA ?
900                         "SS_OUTPUT_ENA " : "");
901
902         p += sprintf(p, "Vcc      : %d\n", pcmcia_socket[sock].cs_state.Vcc);
903         p += sprintf(p, "Vpp      : %d\n", pcmcia_socket[sock].cs_state.Vpp);
904         p += sprintf(p, "irq      : %d\n", pcmcia_socket[sock].cs_state.io_irq);
905         p += sprintf(p, "I/O      : %u\n", pcmcia_socket[sock].speed_io);
906         p += sprintf(p, "attribute: %u\n", pcmcia_socket[sock].speed_attr);
907         p += sprintf(p, "common   : %u\n", pcmcia_socket[sock].speed_mem);
908         return p-buf;
909 }
910
911
912 #endif  /* defined(CONFIG_PROC_FS) */