1 /*
2 *
3 * Alchemy Semi Au1000 pcmcia driver
4 *
5 * Copyright 2001-2003 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * ########################################################################
10 *
11 * This program is free software; you can distribute it and/or modify it
12 * under the terms of the GNU General Public License (Version 2) as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 *
24 * ########################################################################
25 *
26 *
27 */
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/config.h>
31 #include <linux/delay.h>
32 #include <linux/ioport.h>
33 #include <linux/kernel.h>
34 #include <linux/tqueue.h>
35 #include <linux/timer.h>
36 #include <linux/mm.h>
37 #include <linux/proc_fs.h>
38 #include <linux/version.h>
39 #include <linux/types.h>
40 #include <linux/vmalloc.h>
41
42 #include <pcmcia/version.h>
43 #include <pcmcia/cs_types.h>
44 #include <pcmcia/cs.h>
45 #include <pcmcia/ss.h>
46 #include <pcmcia/bulkmem.h>
47 #include <pcmcia/cistpl.h>
48 #include <pcmcia/bus_ops.h>
49 #include "cs_internal.h"
50
51 #include <asm/io.h>
52 #include <asm/irq.h>
53 #include <asm/system.h>
54
55 #include <asm/au1000.h>
56 #include <asm/au1000_pcmcia.h>
57
58 #ifdef PCMCIA_DEBUG
59 static int pc_debug;
60 #endif
61
62 MODULE_LICENSE("GPL");
63 MODULE_AUTHOR("Pete Popov, MontaVista Software <ppopov@mvista.com>");
64 MODULE_DESCRIPTION("Linux PCMCIA Card Services: Au1x00 Socket Controller");
65
66 #define MAP_SIZE 0x1000000
67
68 /* This structure maintains housekeeping state for each socket, such
69 * as the last known values of the card detect pins, or the Card Services
70 * callback value associated with the socket:
71 */
72 static struct au1000_pcmcia_socket *pcmcia_socket;
73
74 /* Some boards like to support CF cards as IDE root devices, so they
75 * grab pcmcia sockets directly.
76 */
77 int socket_count;
78 u32 *pcmcia_base_vaddrs[2];
79
80
81 /* Returned by the low-level PCMCIA interface: */
82 static struct pcmcia_low_level *pcmcia_low_level;
83
84 /* Event poll timer structure */
85 static struct timer_list poll_timer;
86
87
88 /* Prototypes for routines which are used internally: */
89
90 static int au1000_pcmcia_driver_init(void);
91 static void au1000_pcmcia_driver_shutdown(void);
92 static void au1000_pcmcia_task_handler(void *data);
93 static void au1000_pcmcia_poll_event(unsigned long data);
94 static void au1000_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs);
95 static struct tq_struct au1000_pcmcia_task;
96
97 #ifdef CONFIG_PROC_FS
98 static int au1000_pcmcia_proc_status(char *buf, char **start,
99 off_t pos, int count, int *eof, void *data);
100 #endif
101
102
103 /* Prototypes for operations which are exported to the
104 * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core:
105 */
106
107 static int au1000_pcmcia_init(u32 sock);
108 static int au1000_pcmcia_suspend(u32 sock);
109 static int au1000_pcmcia_register_callback(u32 sock,
110 void (*handler)(void *, u32), void *info);
111 static int au1000_pcmcia_inquire_socket(u32 sock, socket_cap_t *cap);
112 static int au1000_pcmcia_get_status(u32 sock, u_int *value);
113 static int au1000_pcmcia_get_socket(u32 sock, socket_state_t *state);
114 static int au1000_pcmcia_set_socket(u32 sock, socket_state_t *state);
115 static int au1000_pcmcia_get_io_map(u32 sock, struct pccard_io_map *io);
116 static int au1000_pcmcia_set_io_map(u32 sock, struct pccard_io_map *io);
117 static int au1000_pcmcia_get_mem_map(u32 sock, struct pccard_mem_map *mem);
118 static int au1000_pcmcia_set_mem_map(u32 sock, struct pccard_mem_map *mem);
119 #ifdef CONFIG_PROC_FS
120 static void au1000_pcmcia_proc_setup(u32 sock, struct proc_dir_entry *base);
121 #endif
122
123 static struct pccard_operations au1000_pcmcia_operations = {
124 au1000_pcmcia_init,
125 au1000_pcmcia_suspend,
126 au1000_pcmcia_register_callback,
127 au1000_pcmcia_inquire_socket,
128 au1000_pcmcia_get_status,
129 au1000_pcmcia_get_socket,
130 au1000_pcmcia_set_socket,
131 au1000_pcmcia_get_io_map,
132 au1000_pcmcia_set_io_map,
133 au1000_pcmcia_get_mem_map,
134 au1000_pcmcia_set_mem_map,
135 #ifdef CONFIG_PROC_FS
136 au1000_pcmcia_proc_setup
137 #endif
138 };
139
140 static spinlock_t pcmcia_lock = SPIN_LOCK_UNLOCKED;
141
142 extern const unsigned long mips_io_port_base;
143
au1000_pcmcia_driver_init(void)144 static int __init au1000_pcmcia_driver_init(void)
145 {
146 servinfo_t info;
147 struct pcmcia_init pcmcia_init;
148 struct pcmcia_state state;
149 unsigned int i;
150
151 printk("\nAu1x00 PCMCIA (CS release %s)\n", CS_RELEASE);
152
153 #ifndef CONFIG_64BIT_PHYS_ADDR
154 printk(KERN_ERR "Au1x00 PCMCIA 36 bit IO support not enabled\n");
155 return -1;
156 #endif
157
158 CardServices(GetCardServicesInfo, &info);
159
160 if(info.Revision!=CS_RELEASE_CODE){
161 printk(KERN_ERR "Card Services release codes do not match\n");
162 return -1;
163 }
164
165 pcmcia_low_level=&au1x00_pcmcia_ops;
166 pcmcia_init.handler=au1000_pcmcia_interrupt;
167 if((socket_count=pcmcia_low_level->init(&pcmcia_init))<0) {
168 printk(KERN_ERR "Unable to initialize PCMCIA service.\n");
169 return -EIO;
170 }
171
172 /* NOTE: the chip select must already be setup */
173
174 pcmcia_socket =
175 kmalloc(sizeof(struct au1000_pcmcia_socket) * socket_count,
176 GFP_KERNEL);
177 if (!pcmcia_socket) {
178 printk(KERN_ERR "Card Services can't get memory \n");
179 return -1;
180 }
181 memset(pcmcia_socket, 0,
182 sizeof(struct au1000_pcmcia_socket) * socket_count);
183
184 /*
185 * Assuming max of 2 sockets, which the Au1000 supports.
186 * WARNING: the Pb1000 has two sockets, and both work, but you
187 * can't use them both at the same time due to glue logic conflicts.
188 */
189 for(i=0; i < socket_count; i++) {
190
191 if(pcmcia_low_level->socket_state(i, &state)<0){
192 printk(KERN_ERR "Unable to get PCMCIA status\n");
193 return -EIO;
194 }
195 pcmcia_socket[i].k_state=state;
196 pcmcia_socket[i].cs_state.csc_mask=SS_DETECT;
197
198 /*
199 * PCMCIA drivers use the inb/outb macros to access the
200 * IO registers. Since mips_io_port_base is added to the
201 * access address, we need to subtract it here.
202 */
203 if (i == 0) {
204 pcmcia_socket[i].virt_io =
205 (u32)ioremap((ioaddr_t)AU1X_SOCK0_IO, 0x1000) -
206 mips_io_port_base;
207 pcmcia_socket[i].phys_attr =
208 (ioaddr_t)AU1X_SOCK0_PHYS_ATTR;
209 pcmcia_socket[i].phys_mem =
210 (ioaddr_t)AU1X_SOCK0_PHYS_MEM;
211 }
212 #ifdef AU1X_SOCK1_IO /* revisit */
213 else {
214 pcmcia_socket[i].virt_io =
215 (u32)ioremap((ioaddr_t)AU1X_SOCK1_IO, 0x1000) -
216 mips_io_port_base;
217 pcmcia_socket[i].phys_attr =
218 (ioaddr_t)AU1X_SOCK1_PHYS_ATTR;
219 pcmcia_socket[i].phys_mem =
220 (ioaddr_t)AU1X_SOCK1_PHYS_MEM;
221 }
222 #endif
223 pcmcia_base_vaddrs[i] = (u32 *)pcmcia_socket[i].virt_io;
224 }
225
226 /* Only advertise as many sockets as we can detect: */
227 if(register_ss_entry(socket_count, &au1000_pcmcia_operations)<0){
228 printk(KERN_ERR "Unable to register socket service routine\n");
229 return -ENXIO;
230 }
231
232 /* Start the event poll timer.
233 * It will reschedule by itself afterwards.
234 */
235 au1000_pcmcia_poll_event(0);
236
237 DEBUG(1, "au1000: initialization complete\n");
238 return 0;
239
240 } /* au1000_pcmcia_driver_init() */
241
242 module_init(au1000_pcmcia_driver_init);
243
au1000_pcmcia_driver_shutdown(void)244 static void __exit au1000_pcmcia_driver_shutdown(void)
245 {
246 int i;
247
248 del_timer_sync(&poll_timer);
249 unregister_ss_entry(&au1000_pcmcia_operations);
250 pcmcia_low_level->shutdown();
251 flush_scheduled_tasks();
252 for(i=0; i < socket_count; i++) {
253 if (pcmcia_socket[i].virt_io)
254 iounmap((void *)pcmcia_socket[i].virt_io +
255 mips_io_port_base);
256 }
257 DEBUG(1, "au1000: shutdown complete\n");
258 }
259
260 module_exit(au1000_pcmcia_driver_shutdown);
261
au1000_pcmcia_init(unsigned int sock)262 static int au1000_pcmcia_init(unsigned int sock) { return 0; }
263
au1000_pcmcia_suspend(unsigned int sock)264 static int au1000_pcmcia_suspend(unsigned int sock)
265 {
266 return 0;
267 }
268
269
270 static inline unsigned
au1000_pcmcia_events(struct pcmcia_state * state,struct pcmcia_state * prev_state,unsigned int mask,unsigned int flags)271 au1000_pcmcia_events(struct pcmcia_state *state,
272 struct pcmcia_state *prev_state,
273 unsigned int mask, unsigned int flags)
274 {
275 unsigned int events=0;
276
277 if(state->detect!=prev_state->detect){
278 DEBUG(2, "%s(): card detect value %u\n",
279 __FUNCTION__, state->detect);
280 events |= mask&SS_DETECT;
281 }
282
283
284 if(state->ready!=prev_state->ready){
285 DEBUG(2, "%s(): card ready value %u\n",
286 __FUNCTION__, state->ready);
287 events |= mask&((flags&SS_IOCARD)?0:SS_READY);
288 }
289
290 *prev_state=*state;
291 return events;
292
293 } /* au1000_pcmcia_events() */
294
295
296 /*
297 * Au1000_pcmcia_task_handler()
298 * Processes socket events.
299 */
au1000_pcmcia_task_handler(void * data)300 static void au1000_pcmcia_task_handler(void *data)
301 {
302 struct pcmcia_state state;
303 int i, events, irq_status;
304
305 for(i=0; i<socket_count; i++) {
306 if((irq_status = pcmcia_low_level->socket_state(i, &state))<0)
307 printk(KERN_ERR "low-level PCMCIA error\n");
308
309 events = au1000_pcmcia_events(&state,
310 &pcmcia_socket[i].k_state,
311 pcmcia_socket[i].cs_state.csc_mask,
312 pcmcia_socket[i].cs_state.flags);
313 if(pcmcia_socket[i].handler!=NULL) {
314 pcmcia_socket[i].handler(pcmcia_socket[i].handler_info,
315 events);
316 }
317 }
318
319 } /* au1000_pcmcia_task_handler() */
320
321 static struct tq_struct au1000_pcmcia_task = {
322 routine: au1000_pcmcia_task_handler
323 };
324
325
au1000_pcmcia_poll_event(unsigned long dummy)326 static void au1000_pcmcia_poll_event(unsigned long dummy)
327 {
328 poll_timer.function = au1000_pcmcia_poll_event;
329 poll_timer.expires = jiffies + AU1000_PCMCIA_POLL_PERIOD;
330 add_timer(&poll_timer);
331 schedule_task(&au1000_pcmcia_task);
332 }
333
334
335 /*
336 * au1000_pcmcia_interrupt()
337 * The actual interrupt work is performed by au1000_pcmcia_task(),
338 * because the Card Services event handling code performs scheduling
339 * operations which cannot be executed from within an interrupt context.
340 */
341 static void
au1000_pcmcia_interrupt(int irq,void * dev,struct pt_regs * regs)342 au1000_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
343 {
344 schedule_task(&au1000_pcmcia_task);
345 }
346
347
348 static int
au1000_pcmcia_register_callback(unsigned int sock,void (* handler)(void *,unsigned int),void * info)349 au1000_pcmcia_register_callback(unsigned int sock,
350 void (*handler)(void *, unsigned int), void *info)
351 {
352 if(handler==NULL){
353 pcmcia_socket[sock].handler=NULL;
354 MOD_DEC_USE_COUNT;
355 } else {
356 MOD_INC_USE_COUNT;
357 pcmcia_socket[sock].handler=handler;
358 pcmcia_socket[sock].handler_info=info;
359 }
360 return 0;
361 }
362
363
364 /* au1000_pcmcia_inquire_socket()
365 *
366 * From the sa1100 socket driver :
367 *
368 * Implements the inquire_socket() operation for the in-kernel PCMCIA
369 * service (formerly SS_InquireSocket in Card Services). We set
370 * SS_CAP_STATIC_MAP, which disables the memory resource database check.
371 * (Mapped memory is set up within the socket driver itself.)
372 *
373 * In conjunction with the STATIC_MAP capability is a new field,
374 * `io_offset', recommended by David Hinds. Rather than go through
375 * the SetIOMap interface (which is not quite suited for communicating
376 * window locations up from the socket driver), we just pass up
377 * an offset which is applied to client-requested base I/O addresses
378 * in alloc_io_space().
379 *
380 * Returns: 0 on success, -1 if no pin has been configured for `sock'
381 */
au1000_pcmcia_inquire_socket(unsigned int sock,socket_cap_t * cap)382 static int au1000_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap)
383 {
384 struct pcmcia_irq_info irq_info;
385
386 if(sock > socket_count){
387 printk(KERN_ERR "au1000: socket %u not configured\n", sock);
388 return -1;
389 }
390
391 /* from the sa1100_generic driver: */
392
393 /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
394 * force_low argument to validate_mem() in rsrc_mgr.c -- since in
395 * general, the mapped * addresses of the PCMCIA memory regions
396 * will not be within 0xffff, setting force_low would be
397 * undesirable.
398 *
399 * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
400 * resource database; we instead pass up physical address ranges
401 * and allow other parts of Card Services to deal with remapping.
402 *
403 * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
404 * not 32-bit CardBus devices.
405 */
406 cap->features=(SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD);
407
408 irq_info.sock=sock;
409 irq_info.irq=-1;
410
411 if(pcmcia_low_level->get_irq_info(&irq_info)<0){
412 printk(KERN_ERR "Error obtaining IRQ info socket %u\n", sock);
413 return -1;
414 }
415
416 cap->irq_mask=0;
417 cap->map_size=MAP_SIZE;
418 cap->pci_irq=irq_info.irq;
419 cap->io_offset=pcmcia_socket[sock].virt_io;
420
421 return 0;
422
423 } /* au1000_pcmcia_inquire_socket() */
424
425
426 static int
au1000_pcmcia_get_status(unsigned int sock,unsigned int * status)427 au1000_pcmcia_get_status(unsigned int sock, unsigned int *status)
428 {
429 struct pcmcia_state state;
430
431
432 if((pcmcia_low_level->socket_state(sock, &state))<0){
433 printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
434 return -1;
435 }
436
437 pcmcia_socket[sock].k_state = state;
438
439 *status = state.detect?SS_DETECT:0;
440
441 *status |= state.ready?SS_READY:0;
442
443 *status |= pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0;
444
445 if(pcmcia_socket[sock].cs_state.flags&SS_IOCARD)
446 *status |= state.bvd1?SS_STSCHG:0;
447 else {
448 if(state.bvd1==0)
449 *status |= SS_BATDEAD;
450 else if(state.bvd2 == 0)
451 *status |= SS_BATWARN;
452 }
453
454 *status|=state.vs_3v?SS_3VCARD:0;
455
456 *status|=state.vs_Xv?SS_XVCARD:0;
457
458 DEBUG(2, "\tstatus: %s%s%s%s%s%s%s%s\n",
459 (*status&SS_DETECT)?"DETECT ":"",
460 (*status&SS_READY)?"READY ":"",
461 (*status&SS_BATDEAD)?"BATDEAD ":"",
462 (*status&SS_BATWARN)?"BATWARN ":"",
463 (*status&SS_POWERON)?"POWERON ":"",
464 (*status&SS_STSCHG)?"STSCHG ":"",
465 (*status&SS_3VCARD)?"3VCARD ":"",
466 (*status&SS_XVCARD)?"XVCARD ":"");
467
468 return 0;
469
470 } /* au1000_pcmcia_get_status() */
471
472
473 static int
au1000_pcmcia_get_socket(unsigned int sock,socket_state_t * state)474 au1000_pcmcia_get_socket(unsigned int sock, socket_state_t *state)
475 {
476 *state = pcmcia_socket[sock].cs_state;
477 return 0;
478 }
479
480
481 static int
au1000_pcmcia_set_socket(unsigned int sock,socket_state_t * state)482 au1000_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
483 {
484 struct pcmcia_configure configure;
485
486 DEBUG(2, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
487 "\tVcc %d Vpp %d irq %d\n",
488 (state->csc_mask==0)?"<NONE>":"",
489 (state->csc_mask&SS_DETECT)?"DETECT ":"",
490 (state->csc_mask&SS_READY)?"READY ":"",
491 (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
492 (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
493 (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
494 (state->flags==0)?"<NONE>":"",
495 (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
496 (state->flags&SS_IOCARD)?"IOCARD ":"",
497 (state->flags&SS_RESET)?"RESET ":"",
498 (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
499 (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
500 state->Vcc, state->Vpp, state->io_irq);
501
502 configure.sock=sock;
503 configure.vcc=state->Vcc;
504 configure.vpp=state->Vpp;
505 configure.output=(state->flags&SS_OUTPUT_ENA)?1:0;
506 configure.speaker=(state->flags&SS_SPKR_ENA)?1:0;
507 configure.reset=(state->flags&SS_RESET)?1:0;
508
509 if(pcmcia_low_level->configure_socket(&configure)<0){
510 printk(KERN_ERR "Unable to configure socket %u\n", sock);
511 return -1;
512 }
513
514 pcmcia_socket[sock].cs_state = *state;
515 return 0;
516
517 } /* au1000_pcmcia_set_socket() */
518
519
520 static int
au1000_pcmcia_get_io_map(unsigned int sock,struct pccard_io_map * map)521 au1000_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map)
522 {
523 DEBUG(1, "au1000_pcmcia_get_io_map: sock %d\n", sock);
524 if(map->map>=MAX_IO_WIN){
525 printk(KERN_ERR "%s(): map (%d) out of range\n",
526 __FUNCTION__, map->map);
527 return -1;
528 }
529 *map=pcmcia_socket[sock].io_map[map->map];
530 return 0;
531 }
532
533
534 int
au1000_pcmcia_set_io_map(unsigned int sock,struct pccard_io_map * map)535 au1000_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
536 {
537 unsigned int speed;
538 unsigned long start;
539
540 if(map->map>=MAX_IO_WIN){
541 printk(KERN_ERR "%s(): map (%d) out of range\n",
542 __FUNCTION__, map->map);
543 return -1;
544 }
545
546 if(map->flags&MAP_ACTIVE){
547 speed=(map->speed>0)?map->speed:AU1000_PCMCIA_IO_SPEED;
548 pcmcia_socket[sock].speed_io=speed;
549 }
550
551 start=map->start;
552
553 if(map->stop==1) {
554 map->stop=PAGE_SIZE-1;
555 }
556
557 map->start=pcmcia_socket[sock].virt_io;
558 map->stop=map->start+(map->stop-start);
559 pcmcia_socket[sock].io_map[map->map]=*map;
560 DEBUG(3, "set_io_map %d start %x stop %x\n",
561 map->map, map->start, map->stop);
562 return 0;
563
564 } /* au1000_pcmcia_set_io_map() */
565
566
567 static int
au1000_pcmcia_get_mem_map(unsigned int sock,struct pccard_mem_map * map)568 au1000_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map)
569 {
570
571 if(map->map>=MAX_WIN) {
572 printk(KERN_ERR "%s(): map (%d) out of range\n",
573 __FUNCTION__, map->map);
574 return -1;
575 }
576 *map=pcmcia_socket[sock].mem_map[map->map];
577 return 0;
578 }
579
580
581 static int
au1000_pcmcia_set_mem_map(unsigned int sock,struct pccard_mem_map * map)582 au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
583 {
584 unsigned int speed;
585 unsigned long start;
586 u_long flags;
587
588 if(map->map>=MAX_WIN){
589 printk(KERN_ERR "%s(): map (%d) out of range\n",
590 __FUNCTION__, map->map);
591 return -1;
592 }
593
594 if(map->flags&MAP_ACTIVE){
595 speed=(map->speed>0)?map->speed:AU1000_PCMCIA_MEM_SPEED;
596
597 /* TBD */
598 if(map->flags&MAP_ATTRIB){
599 pcmcia_socket[sock].speed_attr=speed;
600 }
601 else {
602 pcmcia_socket[sock].speed_mem=speed;
603 }
604 }
605
606 spin_lock_irqsave(&pcmcia_lock, flags);
607
608 if(map->sys_stop==0)
609 map->sys_stop=MAP_SIZE-1;
610
611 if (map->flags & MAP_ATTRIB) {
612 map->sys_start = pcmcia_socket[sock].phys_attr +
613 map->card_start;
614 }
615 else {
616 map->sys_start = pcmcia_socket[sock].phys_mem +
617 map->card_start;
618 }
619
620 map->sys_stop=map->sys_start+MAP_SIZE;
621 pcmcia_socket[sock].mem_map[map->map]=*map;
622 spin_unlock_irqrestore(&pcmcia_lock, flags);
623 DEBUG(3, "set_mem_map %d start %x stop %x card_start %x\n",
624 map->map, map->sys_start, map->sys_stop,
625 map->card_start);
626 return 0;
627
628 } /* au1000_pcmcia_set_mem_map() */
629
630
631 #if defined(CONFIG_PROC_FS)
632
633 static void
au1000_pcmcia_proc_setup(unsigned int sock,struct proc_dir_entry * base)634 au1000_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
635 {
636 struct proc_dir_entry *entry;
637
638 if((entry=create_proc_entry("status", 0, base))==NULL){
639 printk(KERN_ERR "Unable to install \"status\" procfs entry\n");
640 return;
641 }
642
643 entry->read_proc=au1000_pcmcia_proc_status;
644 entry->data=(void *)sock;
645 }
646
647
648 /* au1000_pcmcia_proc_status()
649 * Implements the /proc/bus/pccard/??/status file.
650 *
651 * Returns: the number of characters added to the buffer
652 */
653 static int
au1000_pcmcia_proc_status(char * buf,char ** start,off_t pos,int count,int * eof,void * data)654 au1000_pcmcia_proc_status(char *buf, char **start, off_t pos,
655 int count, int *eof, void *data)
656 {
657 char *p=buf;
658 unsigned int sock=(unsigned int)data;
659
660 p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n",
661 pcmcia_socket[sock].k_state.detect?"detect ":"",
662 pcmcia_socket[sock].k_state.ready?"ready ":"",
663 pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"",
664 pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"",
665 pcmcia_socket[sock].k_state.wrprot?"wrprot ":"",
666 pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"",
667 pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":"");
668
669 p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n",
670 pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"",
671 pcmcia_socket[sock].k_state.ready?"SS_READY ":"",
672 pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"",
673 pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
674 "SS_IOCARD ":"",
675 (pcmcia_socket[sock].cs_state.flags&SS_IOCARD &&
676 pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"",
677 ((pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
678 (pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"",
679 ((pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
680 (pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"",
681 pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"",
682 pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":"");
683
684 p+=sprintf(p, "mask : %s%s%s%s%s\n",
685 pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\
686 "SS_DETECT ":"",
687 pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\
688 "SS_READY ":"",
689 pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\
690 "SS_BATDEAD ":"",
691 pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\
692 "SS_BATWARN ":"",
693 pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\
694 "SS_STSCHG ":"");
695
696 p+=sprintf(p, "cs_flags : %s%s%s%s%s\n",
697 pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\
698 "SS_PWR_AUTO ":"",
699 pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
700 "SS_IOCARD ":"",
701 pcmcia_socket[sock].cs_state.flags&SS_RESET?\
702 "SS_RESET ":"",
703 pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\
704 "SS_SPKR_ENA ":"",
705 pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\
706 "SS_OUTPUT_ENA ":"");
707
708 p+=sprintf(p, "Vcc : %d\n", pcmcia_socket[sock].cs_state.Vcc);
709 p+=sprintf(p, "Vpp : %d\n", pcmcia_socket[sock].cs_state.Vpp);
710 p+=sprintf(p, "irq : %d\n", pcmcia_socket[sock].cs_state.io_irq);
711 p+=sprintf(p, "I/O : %u\n", pcmcia_socket[sock].speed_io);
712 p+=sprintf(p, "attribute: %u\n", pcmcia_socket[sock].speed_attr);
713 p+=sprintf(p, "common : %u\n", pcmcia_socket[sock].speed_mem);
714 return p-buf;
715 }
716
717
718 #endif /* defined(CONFIG_PROC_FS) */
719