1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/config.h>
37#include <linux/types.h>
38#include <linux/fcntl.h>
39#include <linux/string.h>
40#include <linux/kernel.h>
41#include <linux/errno.h>
42#include <linux/timer.h>
43#include <linux/sched.h>
44#include <linux/slab.h>
45#include <linux/ioport.h>
46#include <linux/delay.h>
47#include <linux/proc_fs.h>
48#include <asm/irq.h>
49#include <asm/io.h>
50#include <asm/bitops.h>
51#include <asm/segment.h>
52#include <asm/system.h>
53
54#include <pcmcia/version.h>
55#include <pcmcia/cs_types.h>
56#include <pcmcia/ss.h>
57#include <pcmcia/cs.h>
58
59#include <linux/isapnp.h>
60
61
62#include "i82365.h"
63#include "cirrus.h"
64#include "vg468.h"
65#include "ricoh.h"
66
67#ifdef PCMCIA_DEBUG
68static int pc_debug = PCMCIA_DEBUG;
69MODULE_PARM(pc_debug, "i");
70#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
71static const char *version =
72"i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)";
73#else
74#define DEBUG(n, args...) do { } while (0)
75#endif
76
77static void irq_count(int, void *, struct pt_regs *);
78static inline int _check_irq(int irq, int flags)
79{
80 if (request_irq(irq, irq_count, flags, "x", irq_count) != 0)
81 return -1;
82 free_irq(irq, irq_count);
83 return 0;
84}
85
86
87
88
89
90
91static int i365_base = 0x3e0;
92
93static int extra_sockets = 0;
94
95static int ignore = -1;
96
97static u_int irq_mask = 0xffff;
98static int irq_list[16] = { -1 };
99
100static int cs_irq = 0;
101
102
103static int do_scan = 1;
104
105static int poll_interval = 0;
106
107static int cycle_time = 120;
108
109
110static int has_dma = -1;
111static int has_led = -1;
112static int has_ring = -1;
113static int dynamic_mode = 0;
114static int freq_bypass = -1;
115static int setup_time = -1;
116static int cmd_time = -1;
117static int recov_time = -1;
118
119
120static int async_clock = -1;
121static int cable_mode = -1;
122static int wakeup = 0;
123
124MODULE_PARM(i365_base, "i");
125MODULE_PARM(ignore, "i");
126MODULE_PARM(extra_sockets, "i");
127MODULE_PARM(irq_mask, "i");
128MODULE_PARM(irq_list, "1-16i");
129MODULE_PARM(cs_irq, "i");
130MODULE_PARM(async_clock, "i");
131MODULE_PARM(cable_mode, "i");
132MODULE_PARM(wakeup, "i");
133
134MODULE_PARM(do_scan, "i");
135MODULE_PARM(poll_interval, "i");
136MODULE_PARM(cycle_time, "i");
137MODULE_PARM(has_dma, "i");
138MODULE_PARM(has_led, "i");
139MODULE_PARM(has_ring, "i");
140MODULE_PARM(dynamic_mode, "i");
141MODULE_PARM(freq_bypass, "i");
142MODULE_PARM(setup_time, "i");
143MODULE_PARM(cmd_time, "i");
144MODULE_PARM(recov_time, "i");
145
146
147
148typedef struct cirrus_state_t {
149 u_char misc1, misc2;
150 u_char timer[6];
151} cirrus_state_t;
152
153typedef struct vg46x_state_t {
154 u_char ctl, ema;
155} vg46x_state_t;
156
157typedef struct socket_info_t {
158 u_short type, flags;
159 socket_cap_t cap;
160 ioaddr_t ioaddr;
161 u_short psock;
162 u_char cs_irq, intr;
163 void (*handler)(void *info, u_int events);
164 void *info;
165#ifdef CONFIG_PROC_FS
166 struct proc_dir_entry *proc;
167#endif
168 union {
169 cirrus_state_t cirrus;
170 vg46x_state_t vg46x;
171 } state;
172} socket_info_t;
173
174
175static int sockets = 0;
176static socket_info_t socket[8] = {
177 { 0, },
178};
179
180
181#define I365_MASK 0xdeb8
182
183static int grab_irq;
184static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
185#define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
186#define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
187
188static struct timer_list poll_timer;
189
190
191
192
193typedef enum pcic_id {
194 IS_I82365A, IS_I82365B, IS_I82365DF,
195 IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
196 IS_PD6710, IS_PD672X, IS_VT83C469,
197} pcic_id;
198
199
200#define IS_VADEM 0x0001
201#define IS_CIRRUS 0x0002
202#define IS_VIA 0x0010
203#define IS_UNKNOWN 0x0400
204#define IS_VG_PWR 0x0800
205#define IS_DF_PWR 0x1000
206#define IS_ALIVE 0x8000
207
208typedef struct pcic_t {
209 char *name;
210 u_short flags;
211} pcic_t;
212
213static pcic_t pcic[] = {
214 { "Intel i82365sl A step", 0 },
215 { "Intel i82365sl B step", 0 },
216 { "Intel i82365sl DF", IS_DF_PWR },
217 { "IBM Clone", 0 },
218 { "Ricoh RF5C296/396", 0 },
219 { "VLSI 82C146", 0 },
220 { "Vadem VG-468", IS_VADEM },
221 { "Vadem VG-469", IS_VADEM|IS_VG_PWR },
222 { "Cirrus PD6710", IS_CIRRUS },
223 { "Cirrus PD672x", IS_CIRRUS },
224 { "VIA VT83C469", IS_CIRRUS|IS_VIA },
225};
226
227#define PCIC_COUNT (sizeof(pcic)/sizeof(pcic_t))
228
229
230
231static spinlock_t bus_lock = SPIN_LOCK_UNLOCKED;
232
233static u_char i365_get(u_short sock, u_short reg)
234{
235 unsigned long flags;
236 spin_lock_irqsave(&bus_lock,flags);
237 {
238 ioaddr_t port = socket[sock].ioaddr;
239 u_char val;
240 reg = I365_REG(socket[sock].psock, reg);
241 outb(reg, port); val = inb(port+1);
242 spin_unlock_irqrestore(&bus_lock,flags);
243 return val;
244 }
245}
246
247static void i365_set(u_short sock, u_short reg, u_char data)
248{
249 unsigned long flags;
250 spin_lock_irqsave(&bus_lock,flags);
251 {
252 ioaddr_t port = socket[sock].ioaddr;
253 u_char val = I365_REG(socket[sock].psock, reg);
254 outb(val, port); outb(data, port+1);
255 spin_unlock_irqrestore(&bus_lock,flags);
256 }
257}
258
259static void i365_bset(u_short sock, u_short reg, u_char mask)
260{
261 u_char d = i365_get(sock, reg);
262 d |= mask;
263 i365_set(sock, reg, d);
264}
265
266static void i365_bclr(u_short sock, u_short reg, u_char mask)
267{
268 u_char d = i365_get(sock, reg);
269 d &= ~mask;
270 i365_set(sock, reg, d);
271}
272
273static void i365_bflip(u_short sock, u_short reg, u_char mask, int b)
274{
275 u_char d = i365_get(sock, reg);
276 if (b)
277 d |= mask;
278 else
279 d &= ~mask;
280 i365_set(sock, reg, d);
281}
282
283static u_short i365_get_pair(u_short sock, u_short reg)
284{
285 u_short a, b;
286 a = i365_get(sock, reg);
287 b = i365_get(sock, reg+1);
288 return (a + (b<<8));
289}
290
291static void i365_set_pair(u_short sock, u_short reg, u_short data)
292{
293 i365_set(sock, reg, data & 0xff);
294 i365_set(sock, reg+1, data >> 8);
295}
296
297
298
299
300
301
302
303
304
305
306
307
308#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
309
310static void cirrus_get_state(u_short s)
311{
312 int i;
313 cirrus_state_t *p = &socket[s].state.cirrus;
314 p->misc1 = i365_get(s, PD67_MISC_CTL_1);
315 p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
316 p->misc2 = i365_get(s, PD67_MISC_CTL_2);
317 for (i = 0; i < 6; i++)
318 p->timer[i] = i365_get(s, PD67_TIME_SETUP(0)+i);
319}
320
321static void cirrus_set_state(u_short s)
322{
323 int i;
324 u_char misc;
325 cirrus_state_t *p = &socket[s].state.cirrus;
326
327 misc = i365_get(s, PD67_MISC_CTL_2);
328 i365_set(s, PD67_MISC_CTL_2, p->misc2);
329 if (misc & PD67_MC2_SUSPEND) mdelay(50);
330 misc = i365_get(s, PD67_MISC_CTL_1);
331 misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
332 i365_set(s, PD67_MISC_CTL_1, misc | p->misc1);
333 for (i = 0; i < 6; i++)
334 i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]);
335}
336
337static u_int __init cirrus_set_opts(u_short s, char *buf)
338{
339 socket_info_t *t = &socket[s];
340 cirrus_state_t *p = &socket[s].state.cirrus;
341 u_int mask = 0xffff;
342
343 if (has_ring == -1) has_ring = 1;
344 flip(p->misc2, PD67_MC2_IRQ15_RI, has_ring);
345 flip(p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode);
346 flip(p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass);
347 if (p->misc2 & PD67_MC2_IRQ15_RI)
348 strcat(buf, " [ring]");
349 if (p->misc2 & PD67_MC2_DYNAMIC_MODE)
350 strcat(buf, " [dyn mode]");
351 if (p->misc2 & PD67_MC2_FREQ_BYPASS)
352 strcat(buf, " [freq bypass]");
353 if (p->misc1 & PD67_MC1_INPACK_ENA)
354 strcat(buf, " [inpack]");
355 if (p->misc2 & PD67_MC2_IRQ15_RI)
356 mask &= ~0x8000;
357 if (has_led > 0) {
358 strcat(buf, " [led]");
359 mask &= ~0x1000;
360 }
361 if (has_dma > 0) {
362 strcat(buf, " [dma]");
363 mask &= ~0x0600;
364 }
365 if (!(t->flags & IS_VIA)) {
366 if (setup_time >= 0)
367 p->timer[0] = p->timer[3] = setup_time;
368 if (cmd_time > 0) {
369 p->timer[1] = cmd_time;
370 p->timer[4] = cmd_time*2+4;
371 }
372 if (p->timer[1] == 0) {
373 p->timer[1] = 6; p->timer[4] = 16;
374 if (p->timer[0] == 0)
375 p->timer[0] = p->timer[3] = 1;
376 }
377 if (recov_time >= 0)
378 p->timer[2] = p->timer[5] = recov_time;
379 buf += strlen(buf);
380 sprintf(buf, " [%d/%d/%d] [%d/%d/%d]", p->timer[0], p->timer[1],
381 p->timer[2], p->timer[3], p->timer[4], p->timer[5]);
382 }
383 return mask;
384}
385
386
387
388
389
390
391
392
393
394static void vg46x_get_state(u_short s)
395{
396 vg46x_state_t *p = &socket[s].state.vg46x;
397 p->ctl = i365_get(s, VG468_CTL);
398 if (socket[s].type == IS_VG469)
399 p->ema = i365_get(s, VG469_EXT_MODE);
400}
401
402static void vg46x_set_state(u_short s)
403{
404 vg46x_state_t *p = &socket[s].state.vg46x;
405 i365_set(s, VG468_CTL, p->ctl);
406 if (socket[s].type == IS_VG469)
407 i365_set(s, VG469_EXT_MODE, p->ema);
408}
409
410static u_int __init vg46x_set_opts(u_short s, char *buf)
411{
412 vg46x_state_t *p = &socket[s].state.vg46x;
413
414 flip(p->ctl, VG468_CTL_ASYNC, async_clock);
415 flip(p->ema, VG469_MODE_CABLE, cable_mode);
416 if (p->ctl & VG468_CTL_ASYNC)
417 strcat(buf, " [async]");
418 if (p->ctl & VG468_CTL_INPACK)
419 strcat(buf, " [inpack]");
420 if (socket[s].type == IS_VG469) {
421 u_char vsel = i365_get(s, VG469_VSELECT);
422 if (vsel & VG469_VSEL_EXT_STAT) {
423 strcat(buf, " [ext mode]");
424 if (vsel & VG469_VSEL_EXT_BUS)
425 strcat(buf, " [isa buf]");
426 }
427 if (p->ema & VG469_MODE_CABLE)
428 strcat(buf, " [cable]");
429 if (p->ema & VG469_MODE_COMPAT)
430 strcat(buf, " [c step]");
431 }
432 return 0xffff;
433}
434
435
436
437
438
439
440
441static void get_bridge_state(u_short s)
442{
443 socket_info_t *t = &socket[s];
444 if (t->flags & IS_CIRRUS)
445 cirrus_get_state(s);
446 else if (t->flags & IS_VADEM)
447 vg46x_get_state(s);
448}
449
450static void set_bridge_state(u_short s)
451{
452 socket_info_t *t = &socket[s];
453 if (t->flags & IS_CIRRUS)
454 cirrus_set_state(s);
455 else {
456 i365_set(s, I365_GBLCTL, 0x00);
457 i365_set(s, I365_GENCTL, 0x00);
458 }
459 i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr);
460 if (t->flags & IS_VADEM)
461 vg46x_set_state(s);
462}
463
464static u_int __init set_bridge_opts(u_short s, u_short ns)
465{
466 u_short i;
467 u_int m = 0xffff;
468 char buf[128];
469
470 for (i = s; i < s+ns; i++) {
471 if (socket[i].flags & IS_ALIVE) {
472 printk(KERN_INFO " host opts [%d]: already alive!\n", i);
473 continue;
474 }
475 buf[0] = '\0';
476 get_bridge_state(i);
477 if (socket[i].flags & IS_CIRRUS)
478 m = cirrus_set_opts(i, buf);
479 else if (socket[i].flags & IS_VADEM)
480 m = vg46x_set_opts(i, buf);
481 set_bridge_state(i);
482 printk(KERN_INFO " host opts [%d]:%s\n", i,
483 (*buf) ? buf : " none");
484 }
485 return m;
486}
487
488
489
490
491
492
493
494static volatile u_int irq_hits;
495static u_short irq_sock;
496
497static void irq_count(int irq, void *dev, struct pt_regs *regs)
498{
499 i365_get(irq_sock, I365_CSC);
500 irq_hits++;
501 DEBUG(2, "-> hit on irq %d\n", irq);
502}
503
504static u_int __init test_irq(u_short sock, int irq)
505{
506 DEBUG(2, " testing ISA irq %d\n", irq);
507 if (request_irq(irq, irq_count, 0, "scan", irq_count) != 0)
508 return 1;
509 irq_hits = 0; irq_sock = sock;
510 __set_current_state(TASK_UNINTERRUPTIBLE);
511 schedule_timeout(HZ/100);
512 if (irq_hits) {
513 free_irq(irq, irq_count);
514 DEBUG(2, " spurious hit!\n");
515 return 1;
516 }
517
518
519 i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
520 i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
521 udelay(1000);
522
523 free_irq(irq, irq_count);
524
525
526 i365_set(sock, I365_CSCINT, 0);
527 DEBUG(2, " hits = %d\n", irq_hits);
528
529 return (irq_hits != 1);
530}
531
532static u_int __init isa_scan(u_short sock, u_int mask0)
533{
534 u_int mask1 = 0;
535 int i;
536
537#ifdef __alpha__
538#define PIC 0x4d0
539
540 mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
541#endif
542
543 if (do_scan) {
544 set_bridge_state(sock);
545 i365_set(sock, I365_CSCINT, 0);
546 for (i = 0; i < 16; i++)
547 if ((mask0 & (1 << i)) && (test_irq(sock, i) == 0))
548 mask1 |= (1 << i);
549 for (i = 0; i < 16; i++)
550 if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
551 mask1 ^= (1 << i);
552 }
553
554 printk(KERN_INFO " ISA irqs (");
555 if (mask1) {
556 printk("scanned");
557 } else {
558
559 for (i = 0; i < 16; i++)
560 if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0))
561 mask1 |= (1 << i);
562 printk("default");
563
564 if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
565 }
566 printk(") = ");
567
568 for (i = 0; i < 16; i++)
569 if (mask1 & (1<<i))
570 printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
571 if (mask1 == 0) printk("none!");
572
573 return mask1;
574}
575
576
577
578
579
580static int to_cycles(int ns)
581{
582 return ns/cycle_time;
583}
584
585static int to_ns(int cycles)
586{
587 return cycle_time*cycles;
588}
589
590
591
592static int __init identify(u_short port, u_short sock)
593{
594 u_char val;
595 int type = -1;
596
597
598 socket[sockets].ioaddr = port;
599 socket[sockets].psock = sock;
600
601
602 if (wakeup) {
603 i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
604
605 mdelay(50);
606 }
607
608 if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
609 return -1;
610 switch (val) {
611 case 0x82:
612 type = IS_I82365A; break;
613 case 0x83:
614 type = IS_I82365B; break;
615 case 0x84:
616 type = IS_I82365DF; break;
617 case 0x88: case 0x89: case 0x8a:
618 type = IS_IBM; break;
619 }
620
621
622 outb(0x0e, port);
623 outb(0x37, port);
624 i365_bset(sockets, VG468_MISC, VG468_MISC_VADEMREV);
625 val = i365_get(sockets, I365_IDENT);
626 if (val & I365_IDENT_VADEM) {
627 i365_bclr(sockets, VG468_MISC, VG468_MISC_VADEMREV);
628 type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;
629 }
630
631
632 val = i365_get(sockets, RF5C_CHIP_ID);
633 if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
634 type = IS_RF5Cx96;
635
636
637 i365_set(sockets, PD67_CHIP_INFO, 0);
638 val = i365_get(sockets, PD67_CHIP_INFO);
639 if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
640 val = i365_get(sockets, PD67_CHIP_INFO);
641 if ((val & PD67_INFO_CHIP_ID) == 0) {
642 type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
643 i365_set(sockets, PD67_EXT_INDEX, 0xe5);
644 if (i365_get(sockets, PD67_EXT_INDEX) != 0xe5)
645 type = IS_VT83C469;
646 }
647 }
648 return type;
649}
650
651
652
653
654
655
656
657
658
659
660static int __init is_alive(u_short sock)
661{
662 u_char stat;
663 u_short start, stop;
664
665 stat = i365_get(sock, I365_STATUS);
666 start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
667 stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
668 if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) &&
669 (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) &&
670 (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) &&
671 (check_region(start, stop-start+1) != 0) &&
672 ((start & 0xfeef) != 0x02e8))
673 return 1;
674 else
675 return 0;
676}
677
678
679
680static void __init add_socket(u_short port, int psock, int type)
681{
682 socket[sockets].ioaddr = port;
683 socket[sockets].psock = psock;
684 socket[sockets].type = type;
685 socket[sockets].flags = pcic[type].flags;
686 if (is_alive(sockets))
687 socket[sockets].flags |= IS_ALIVE;
688 sockets++;
689}
690
691static void __init add_pcic(int ns, int type)
692{
693 u_int mask = 0, i, base;
694 int isa_irq = 0;
695 socket_info_t *t = &socket[sockets-ns];
696
697 base = sockets-ns;
698 if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
699
700 if (base == 0) printk("\n");
701 printk(KERN_INFO " %s", pcic[type].name);
702 printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
703 t->ioaddr, t->psock*0x40);
704 printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
705
706
707 if (irq_list[0] == -1)
708 mask = irq_mask;
709 else
710 for (i = mask = 0; i < 16; i++)
711 mask |= (1<<irq_list[i]);
712 mask &= I365_MASK & set_bridge_opts(base, ns);
713
714 mask = isa_scan(base, mask);
715
716
717 if (!poll_interval) {
718 u_int tmp = (mask & 0xff20);
719 tmp = tmp & (tmp-1);
720 if ((tmp & (tmp-1)) == 0)
721 poll_interval = HZ;
722 }
723
724 if (!grab_irq && (cs_irq || !poll_interval)) {
725
726 u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
727 for (cs_irq = 15; cs_irq > 0; cs_irq--)
728 if ((cs_mask & (1 << cs_irq)) &&
729 (_check_irq(cs_irq, 0) == 0))
730 break;
731 if (cs_irq) {
732 grab_irq = 1;
733 isa_irq = cs_irq;
734 printk(" status change on irq %d\n", cs_irq);
735 }
736 }
737
738 if (!isa_irq) {
739 if (poll_interval == 0)
740 poll_interval = HZ;
741 printk(" polling interval = %d ms\n",
742 poll_interval * 1000 / HZ);
743
744 }
745
746
747 for (i = 0; i < ns; i++) {
748 t[i].cap.features |= SS_CAP_PCCARD;
749 t[i].cap.map_size = 0x1000;
750 t[i].cap.irq_mask = mask;
751 t[i].cs_irq = isa_irq;
752 }
753
754}
755
756
757
758#if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
759#define I82365_ISAPNP
760#endif
761
762#ifdef I82365_ISAPNP
763static struct isapnp_device_id id_table[] __initdata = {
764 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
765 ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" },
766 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
767 ISAPNP_FUNCTION(0x0e01), (unsigned long) "Cirrus Logic CL-PD6720" },
768 { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
769 ISAPNP_FUNCTION(0x0e02), (unsigned long) "VLSI VL82C146" },
770 { 0 }
771};
772MODULE_DEVICE_TABLE(isapnp, id_table);
773
774static struct pci_dev *i82365_pnpdev;
775#endif
776
777static void __init isa_probe(void)
778{
779 int i, j, sock, k, ns, id;
780 ioaddr_t port;
781#ifdef I82365_ISAPNP
782 struct isapnp_device_id *devid;
783 struct pci_dev *dev;
784
785 for (devid = id_table; devid->vendor; devid++) {
786 if ((dev = isapnp_find_dev(NULL, devid->vendor, devid->function, NULL))) {
787 printk("ISAPNP ");
788
789 if (dev->prepare && dev->prepare(dev) < 0) {
790 printk("prepare failed\n");
791 break;
792 }
793
794 if (dev->activate && dev->activate(dev) < 0) {
795 printk("activate failed\n");
796 break;
797 }
798
799 if ((i365_base = pci_resource_start(dev, 0))) {
800 printk("no resources ?\n");
801 break;
802 }
803 i82365_pnpdev = dev;
804 break;
805 }
806 }
807#endif
808
809 if (check_region(i365_base, 2) != 0) {
810 if (sockets == 0)
811 printk("port conflict at %#x\n", i365_base);
812 return;
813 }
814
815 id = identify(i365_base, 0);
816 if ((id == IS_I82365DF) && (identify(i365_base, 1) != id)) {
817 for (i = 0; i < 4; i++) {
818 if (i == ignore) continue;
819 port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);
820 sock = (i & 1) << 1;
821 if (identify(port, sock) == IS_I82365DF) {
822 add_socket(port, sock, IS_VLSI);
823 add_pcic(1, IS_VLSI);
824 }
825 }
826 } else {
827 for (i = 0; i < 8; i += 2) {
828 if (sockets && !extra_sockets && (i == 4))
829 break;
830 port = i365_base + 2*(i>>2);
831 sock = (i & 3);
832 id = identify(port, sock);
833 if (id < 0) continue;
834
835 for (j = ns = 0; j < 2; j++) {
836
837 if ((ignore == i+j) || (identify(port, sock+j) < 0))
838 continue;
839
840 for (k = 0; k <= sockets; k++)
841 i365_set(k, I365_MEM(0)+I365_W_OFF, k);
842 for (k = 0; k <= sockets; k++)
843 if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k)
844 break;
845 if (k <= sockets) break;
846 add_socket(port, sock+j, id); ns++;
847 }
848 if (ns != 0) add_pcic(ns, id);
849 }
850 }
851}
852
853
854
855static u_int pending_events[8];
856static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
857
858static void pcic_bh(void *dummy)
859{
860 u_int events;
861 int i;
862
863 for (i=0; i < sockets; i++) {
864 spin_lock_irq(&pending_event_lock);
865 events = pending_events[i];
866 pending_events[i] = 0;
867 spin_unlock_irq(&pending_event_lock);
868
869
870
871
872
873 if (events & SS_DETECT)
874 mdelay(4);
875 if (socket[i].handler)
876 socket[i].handler(socket[i].info, events);
877 }
878}
879
880static struct tq_struct pcic_task = {
881 routine: pcic_bh
882};
883
884static unsigned long last_detect_jiffies;
885
886static void pcic_interrupt(int irq, void *dev,
887 struct pt_regs *regs)
888{
889 int i, j, csc;
890 u_int events, active;
891 u_long flags = 0;
892
893 DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
894
895 for (j = 0; j < 20; j++) {
896 active = 0;
897 for (i = 0; i < sockets; i++) {
898 if (socket[i].cs_irq != irq)
899 continue;
900 ISA_LOCK(i, flags);
901 csc = i365_get(i, I365_CSC);
902 if ((csc == 0) || (!socket[i].handler) ||
903 (i365_get(i, I365_IDENT) & 0x70)) {
904 ISA_UNLOCK(i, flags);
905 continue;
906 }
907 events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
908
909
910
911
912
913
914
915 if (events) {
916 if ((jiffies - last_detect_jiffies)<(HZ/20))
917 events = 0;
918 last_detect_jiffies = jiffies;
919
920 }
921
922 if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
923 events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
924 else {
925 events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
926 events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
927 events |= (csc & I365_CSC_READY) ? SS_READY : 0;
928 }
929 ISA_UNLOCK(i, flags);
930 DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events);
931
932 if (events) {
933 spin_lock(&pending_event_lock);
934 pending_events[i] |= events;
935 spin_unlock(&pending_event_lock);
936 schedule_task(&pcic_task);
937 }
938 active |= events;
939 }
940 if (!active) break;
941 }
942 if (j == 20)
943 printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n");
944
945 DEBUG(4, "i82365: interrupt done\n");
946}
947
948static void pcic_interrupt_wrapper(u_long data)
949{
950 pcic_interrupt(0, NULL, NULL);
951 poll_timer.expires = jiffies + poll_interval;
952 add_timer(&poll_timer);
953}
954
955
956
957static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
958{
959 socket[sock].handler = handler;
960 socket[sock].info = info;
961 if (handler == NULL) {
962 MOD_DEC_USE_COUNT;
963 } else {
964 MOD_INC_USE_COUNT;
965 }
966 return 0;
967}
968
969
970
971static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap)
972{
973 *cap = socket[sock].cap;
974 return 0;
975}
976
977
978
979static int i365_get_status(u_short sock, u_int *value)
980{
981 u_int status;
982
983 status = i365_get(sock, I365_STATUS);
984 *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
985 ? SS_DETECT : 0;
986
987 if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
988 *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
989 else {
990 *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
991 *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
992 }
993 *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
994 *value |= (status & I365_CS_READY) ? SS_READY : 0;
995 *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
996
997 if (socket[sock].type == IS_VG469) {
998 status = i365_get(sock, VG469_VSENSE);
999 if (socket[sock].psock & 1) {
1000 *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;
1001 *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;
1002 } else {
1003 *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;
1004 *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
1005 }
1006 }
1007
1008 DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
1009 return 0;
1010}
1011
1012
1013
1014static int i365_get_socket(u_short sock, socket_state_t *state)
1015{
1016 socket_info_t *t = &socket[sock];
1017 u_char reg, vcc, vpp;
1018
1019 reg = i365_get(sock, I365_POWER);
1020 state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
1021 state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
1022 vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
1023 state->Vcc = state->Vpp = 0;
1024 if (t->flags & IS_CIRRUS) {
1025 if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {
1026 if (reg & I365_VCC_5V) state->Vcc = 33;
1027 if (vpp == I365_VPP1_5V) state->Vpp = 33;
1028 } else {
1029 if (reg & I365_VCC_5V) state->Vcc = 50;
1030 if (vpp == I365_VPP1_5V) state->Vpp = 50;
1031 }
1032 if (vpp == I365_VPP1_12V) state->Vpp = 120;
1033 } else if (t->flags & IS_VG_PWR) {
1034 if (i365_get(sock, VG469_VSELECT) & VG469_VSEL_VCC) {
1035 if (reg & I365_VCC_5V) state->Vcc = 33;
1036 if (vpp == I365_VPP1_5V) state->Vpp = 33;
1037 } else {
1038 if (reg & I365_VCC_5V) state->Vcc = 50;
1039 if (vpp == I365_VPP1_5V) state->Vpp = 50;
1040 }
1041 if (vpp == I365_VPP1_12V) state->Vpp = 120;
1042 } else if (t->flags & IS_DF_PWR) {
1043 if (vcc == I365_VCC_3V) state->Vcc = 33;
1044 if (vcc == I365_VCC_5V) state->Vcc = 50;
1045 if (vpp == I365_VPP1_5V) state->Vpp = 50;
1046 if (vpp == I365_VPP1_12V) state->Vpp = 120;
1047 } else {
1048 if (reg & I365_VCC_5V) {
1049 state->Vcc = 50;
1050 if (vpp == I365_VPP1_5V) state->Vpp = 50;
1051 if (vpp == I365_VPP1_12V) state->Vpp = 120;
1052 }
1053 }
1054
1055
1056 reg = i365_get(sock, I365_INTCTL);
1057 state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
1058 if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
1059 state->io_irq = reg & I365_IRQ_MASK;
1060
1061
1062 if (t->flags & IS_CIRRUS) {
1063 if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
1064 state->flags |= SS_SPKR_ENA;
1065 }
1066
1067
1068 reg = i365_get(sock, I365_CSCINT);
1069 state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
1070 if (state->flags & SS_IOCARD)
1071 state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
1072 else {
1073 state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
1074 state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
1075 state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
1076 }
1077
1078 DEBUG(1, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
1079 "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
1080 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
1081 return 0;
1082}
1083
1084
1085
1086static int i365_set_socket(u_short sock, socket_state_t *state)
1087{
1088 socket_info_t *t = &socket[sock];
1089 u_char reg;
1090
1091 DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
1092 "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
1093 state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
1094
1095
1096 set_bridge_state(sock);
1097
1098
1099 reg = t->intr;
1100 reg |= state->io_irq;
1101 reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
1102 reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
1103 i365_set(sock, I365_INTCTL, reg);
1104
1105 reg = I365_PWR_NORESET;
1106 if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
1107 if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
1108
1109 if (t->flags & IS_CIRRUS) {
1110 if (state->Vpp != 0) {
1111 if (state->Vpp == 120)
1112 reg |= I365_VPP1_12V;
1113 else if (state->Vpp == state->Vcc)
1114 reg |= I365_VPP1_5V;
1115 else return -EINVAL;
1116 }
1117 if (state->Vcc != 0) {
1118 reg |= I365_VCC_5V;
1119 if (state->Vcc == 33)
1120 i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
1121 else if (state->Vcc == 50)
1122 i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
1123 else return -EINVAL;
1124 }
1125 } else if (t->flags & IS_VG_PWR) {
1126 if (state->Vpp != 0) {
1127 if (state->Vpp == 120)
1128 reg |= I365_VPP1_12V;
1129 else if (state->Vpp == state->Vcc)
1130 reg |= I365_VPP1_5V;
1131 else return -EINVAL;
1132 }
1133 if (state->Vcc != 0) {
1134 reg |= I365_VCC_5V;
1135 if (state->Vcc == 33)
1136 i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC);
1137 else if (state->Vcc == 50)
1138 i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC);
1139 else return -EINVAL;
1140 }
1141 } else if (t->flags & IS_DF_PWR) {
1142 switch (state->Vcc) {
1143 case 0: break;
1144 case 33: reg |= I365_VCC_3V; break;
1145 case 50: reg |= I365_VCC_5V; break;
1146 default: return -EINVAL;
1147 }
1148 switch (state->Vpp) {
1149 case 0: break;
1150 case 50: reg |= I365_VPP1_5V; break;
1151 case 120: reg |= I365_VPP1_12V; break;
1152 default: return -EINVAL;
1153 }
1154 } else {
1155 switch (state->Vcc) {
1156 case 0: break;
1157 case 50: reg |= I365_VCC_5V; break;
1158 default: return -EINVAL;
1159 }
1160 switch (state->Vpp) {
1161 case 0: break;
1162 case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break;
1163 case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break;
1164 default: return -EINVAL;
1165 }
1166 }
1167
1168 if (reg != i365_get(sock, I365_POWER))
1169 i365_set(sock, I365_POWER, reg);
1170
1171
1172 if (t->flags & IS_CIRRUS) {
1173
1174 i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
1175 state->flags & SS_SPKR_ENA);
1176 }
1177
1178
1179 reg = t->cs_irq << 4;
1180 if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
1181 if (state->flags & SS_IOCARD) {
1182 if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
1183 } else {
1184 if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
1185 if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
1186 if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
1187 }
1188 i365_set(sock, I365_CSCINT, reg);
1189 i365_get(sock, I365_CSC);
1190
1191 return 0;
1192}
1193
1194
1195
1196static int i365_get_io_map(u_short sock, struct pccard_io_map *io)
1197{
1198 u_char map, ioctl, addr;
1199
1200 map = io->map;
1201 if (map > 1) return -EINVAL;
1202 io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START);
1203 io->stop = i365_get_pair(sock, I365_IO(map)+I365_W_STOP);
1204 ioctl = i365_get(sock, I365_IOCTL);
1205 addr = i365_get(sock, I365_ADDRWIN);
1206 io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
1207 io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
1208 io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
1209 io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
1210 io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
1211 DEBUG(1, "i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, "
1212 "%#4.4x-%#4.4x\n", sock, map, io->flags, io->speed,
1213 io->start, io->stop);
1214 return 0;
1215}
1216
1217
1218
1219static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
1220{
1221 u_char map, ioctl;
1222
1223 DEBUG(1, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
1224 "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
1225 io->speed, io->start, io->stop);
1226 map = io->map;
1227 if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
1228 (io->stop < io->start)) return -EINVAL;
1229
1230 if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map))
1231 i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map));
1232 i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start);
1233 i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop);
1234 ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
1235 if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
1236 if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
1237 if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
1238 if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
1239 i365_set(sock, I365_IOCTL, ioctl);
1240
1241 if (io->flags & MAP_ACTIVE)
1242 i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map));
1243 return 0;
1244}
1245
1246
1247
1248static int i365_get_mem_map(u_short sock, struct pccard_mem_map *mem)
1249{
1250 u_short base, i;
1251 u_char map, addr;
1252
1253 map = mem->map;
1254 if (map > 4) return -EINVAL;
1255 addr = i365_get(sock, I365_ADDRWIN);
1256 mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
1257 base = I365_MEM(map);
1258
1259 i = i365_get_pair(sock, base+I365_W_START);
1260 mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0;
1261 mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0;
1262 mem->sys_start = ((u_long)(i & 0x0fff) << 12);
1263
1264 i = i365_get_pair(sock, base+I365_W_STOP);
1265 mem->speed = (i & I365_MEM_WS0) ? 1 : 0;
1266 mem->speed += (i & I365_MEM_WS1) ? 2 : 0;
1267 mem->speed = to_ns(mem->speed);
1268 mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff;
1269
1270 i = i365_get_pair(sock, base+I365_W_OFF);
1271 mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
1272 mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0;
1273 mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
1274 mem->card_start &= 0x3ffffff;
1275
1276 DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
1277 "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed,
1278 mem->sys_start, mem->sys_stop, mem->card_start);
1279 return 0;
1280}
1281
1282
1283
1284static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
1285{
1286 u_short base, i;
1287 u_char map;
1288
1289 DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
1290 "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
1291 mem->sys_start, mem->sys_stop, mem->card_start);
1292
1293 map = mem->map;
1294 if ((map > 4) || (mem->card_start > 0x3ffffff) ||
1295 (mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
1296 return -EINVAL;
1297 if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
1298 return -EINVAL;
1299
1300
1301 if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
1302 i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
1303
1304 base = I365_MEM(map);
1305 i = (mem->sys_start >> 12) & 0x0fff;
1306 if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
1307 if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
1308 i365_set_pair(sock, base+I365_W_START, i);
1309
1310 i = (mem->sys_stop >> 12) & 0x0fff;
1311 switch (to_cycles(mem->speed)) {
1312 case 0: break;
1313 case 1: i |= I365_MEM_WS0; break;
1314 case 2: i |= I365_MEM_WS1; break;
1315 default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
1316 }
1317 i365_set_pair(sock, base+I365_W_STOP, i);
1318
1319 i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
1320 if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
1321 if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
1322 i365_set_pair(sock, base+I365_W_OFF, i);
1323
1324
1325 if (mem->flags & MAP_ACTIVE)
1326 i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
1327 return 0;
1328}
1329
1330
1331
1332
1333
1334
1335
1336
1337#ifdef CONFIG_PROC_FS
1338
1339static int proc_read_info(char *buf, char **start, off_t pos,
1340 int count, int *eof, void *data)
1341{
1342 socket_info_t *s = data;
1343 char *p = buf;
1344 p += sprintf(p, "type: %s\npsock: %d\n",
1345 pcic[s->type].name, s->psock);
1346 return (p - buf);
1347}
1348
1349static int proc_read_exca(char *buf, char **start, off_t pos,
1350 int count, int *eof, void *data)
1351{
1352 u_short sock = (socket_info_t *)data - socket;
1353 char *p = buf;
1354 int i, top;
1355
1356 u_long flags = 0;
1357 ISA_LOCK(sock, flags);
1358 top = 0x40;
1359 for (i = 0; i < top; i += 4) {
1360 if (i == 0x50) {
1361 p += sprintf(p, "\n");
1362 i = 0x100;
1363 }
1364 p += sprintf(p, "%02x %02x %02x %02x%s",
1365 i365_get(sock,i), i365_get(sock,i+1),
1366 i365_get(sock,i+2), i365_get(sock,i+3),
1367 ((i % 16) == 12) ? "\n" : " ");
1368 }
1369 ISA_UNLOCK(sock, flags);
1370 return (p - buf);
1371}
1372
1373static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
1374{
1375 socket_info_t *s = &socket[sock];
1376
1377 if (s->flags & IS_ALIVE)
1378 return;
1379
1380 create_proc_read_entry("info", 0, base, proc_read_info, s);
1381 create_proc_read_entry("exca", 0, base, proc_read_exca, s);
1382 s->proc = base;
1383}
1384
1385static void pcic_proc_remove(u_short sock)
1386{
1387 struct proc_dir_entry *base = socket[sock].proc;
1388 if (base == NULL) return;
1389 remove_proc_entry("info", base);
1390 remove_proc_entry("exca", base);
1391}
1392
1393#else
1394
1395#define pcic_proc_setup NULL
1396
1397#endif
1398
1399
1400
1401
1402
1403#define LOCKED(x) do { \
1404 int retval; \
1405 unsigned long flags; \
1406 spin_lock_irqsave(&isa_lock, flags); \
1407 retval = x; \
1408 spin_unlock_irqrestore(&isa_lock, flags); \
1409 return retval; \
1410} while (0)
1411
1412static int pcic_get_status(unsigned int sock, u_int *value)
1413{
1414 if (socket[sock].flags & IS_ALIVE) {
1415 *value = 0;
1416 return -EINVAL;
1417 }
1418
1419 LOCKED(i365_get_status(sock, value));
1420}
1421
1422static int pcic_get_socket(unsigned int sock, socket_state_t *state)
1423{
1424 if (socket[sock].flags & IS_ALIVE)
1425 return -EINVAL;
1426
1427 LOCKED(i365_get_socket(sock, state));
1428}
1429
1430static int pcic_set_socket(unsigned int sock, socket_state_t *state)
1431{
1432 if (socket[sock].flags & IS_ALIVE)
1433 return -EINVAL;
1434
1435 LOCKED(i365_set_socket(sock, state));
1436}
1437
1438static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io)
1439{
1440 if (socket[sock].flags & IS_ALIVE)
1441 return -EINVAL;
1442
1443 LOCKED(i365_get_io_map(sock, io));
1444}
1445
1446static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io)
1447{
1448 if (socket[sock].flags & IS_ALIVE)
1449 return -EINVAL;
1450
1451 LOCKED(i365_set_io_map(sock, io));
1452}
1453
1454static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
1455{
1456 if (socket[sock].flags & IS_ALIVE)
1457 return -EINVAL;
1458
1459 LOCKED(i365_get_mem_map(sock, mem));
1460}
1461
1462static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
1463{
1464 if (socket[sock].flags & IS_ALIVE)
1465 return -EINVAL;
1466
1467 LOCKED(i365_set_mem_map(sock, mem));
1468}
1469
1470static int pcic_init(unsigned int s)
1471{
1472 int i;
1473 pccard_io_map io = { 0, 0, 0, 0, 1 };
1474 pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
1475
1476 mem.sys_stop = 0x1000;
1477 pcic_set_socket(s, &dead_socket);
1478 for (i = 0; i < 2; i++) {
1479 io.map = i;
1480 pcic_set_io_map(s, &io);
1481 }
1482 for (i = 0; i < 5; i++) {
1483 mem.map = i;
1484 pcic_set_mem_map(s, &mem);
1485 }
1486 return 0;
1487}
1488
1489static int pcic_suspend(unsigned int sock)
1490{
1491 return pcic_set_socket(sock, &dead_socket);
1492}
1493
1494static struct pccard_operations pcic_operations = {
1495 pcic_init,
1496 pcic_suspend,
1497 pcic_register_callback,
1498 pcic_inquire_socket,
1499 pcic_get_status,
1500 pcic_get_socket,
1501 pcic_set_socket,
1502 pcic_get_io_map,
1503 pcic_set_io_map,
1504 pcic_get_mem_map,
1505 pcic_set_mem_map,
1506 pcic_proc_setup
1507};
1508
1509
1510
1511static int __init init_i82365(void)
1512{
1513 servinfo_t serv;
1514 pcmcia_get_card_services_info(&serv);
1515 if (serv.Revision != CS_RELEASE_CODE) {
1516 printk(KERN_NOTICE "i82365: Card Services release "
1517 "does not match!\n");
1518 return -1;
1519 }
1520 DEBUG(0, "%s\n", version);
1521 printk(KERN_INFO "Intel ISA PCIC probe: ");
1522 sockets = 0;
1523
1524 isa_probe();
1525
1526 if (sockets == 0) {
1527 printk("not found.\n");
1528 return -ENODEV;
1529 }
1530
1531
1532 if (grab_irq != 0)
1533 request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
1534
1535 if (register_ss_entry(sockets, &pcic_operations) != 0)
1536 printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
1537
1538
1539 if (poll_interval != 0) {
1540 poll_timer.function = pcic_interrupt_wrapper;
1541 poll_timer.data = 0;
1542 init_timer(&poll_timer);
1543 poll_timer.expires = jiffies + poll_interval;
1544 add_timer(&poll_timer);
1545 }
1546
1547 return 0;
1548
1549}
1550
1551static void __exit exit_i82365(void)
1552{
1553 int i;
1554#ifdef CONFIG_PROC_FS
1555 for (i = 0; i < sockets; i++) pcic_proc_remove(i);
1556#endif
1557 unregister_ss_entry(&pcic_operations);
1558 if (poll_interval != 0)
1559 del_timer(&poll_timer);
1560 if (grab_irq != 0)
1561 free_irq(cs_irq, pcic_interrupt);
1562 for (i = 0; i < sockets; i++) {
1563
1564 i365_set(i, I365_CSCINT, 0);
1565 release_region(socket[i].ioaddr, 2);
1566 }
1567#if defined(I82365_ISAPNP)
1568 if (i82365_pnpdev && i82365_pnpdev->deactivate)
1569 i82365_pnpdev->deactivate(i82365_pnpdev);
1570#endif
1571}
1572
1573module_init(init_i82365);
1574module_exit(exit_i82365);
1575MODULE_LICENSE("Dual MPL/GPL");
1576
1577