add a lot of "censored" parts for wlioctl.h (found in allnet tarball)
[openwrt.git] / openwrt / 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) */
This page took 0.113833 seconds and 5 git commands to generate.