diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-06-28 00:46:22 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-28 00:46:22 -0400 |
commit | c36ad397a30fcf9369d82584324cc24189eb6b1c (patch) | |
tree | a5cbb451a2e9ea3ea12b6d279c72d77ac96c3028 | |
parent | c903e41e67046e7f52bbc404bd5aa654d12540cc (diff) | |
parent | 99f95e5286df2f69edab8a04c7080d986ee4233b (diff) |
Merge /spare/repo/linux-2.6/
101 files changed, 5475 insertions, 2795 deletions
diff --git a/Documentation/Changes b/Documentation/Changes index b37600754762..afebdbcd553a 100644 --- a/Documentation/Changes +++ b/Documentation/Changes | |||
@@ -44,9 +44,9 @@ running, the suggested command should tell you. | |||
44 | 44 | ||
45 | Again, keep in mind that this list assumes you are already | 45 | Again, keep in mind that this list assumes you are already |
46 | functionally running a Linux 2.4 kernel. Also, not all tools are | 46 | functionally running a Linux 2.4 kernel. Also, not all tools are |
47 | necessary on all systems; obviously, if you don't have any PCMCIA (PC | 47 | necessary on all systems; obviously, if you don't have any ISDN |
48 | Card) hardware, for example, you probably needn't concern yourself | 48 | hardware, for example, you probably needn't concern yourself with |
49 | with pcmcia-cs. | 49 | isdn4k-utils. |
50 | 50 | ||
51 | o Gnu C 2.95.3 # gcc --version | 51 | o Gnu C 2.95.3 # gcc --version |
52 | o Gnu make 3.79.1 # make --version | 52 | o Gnu make 3.79.1 # make --version |
@@ -57,6 +57,7 @@ o e2fsprogs 1.29 # tune2fs | |||
57 | o jfsutils 1.1.3 # fsck.jfs -V | 57 | o jfsutils 1.1.3 # fsck.jfs -V |
58 | o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs | 58 | o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs |
59 | o xfsprogs 2.6.0 # xfs_db -V | 59 | o xfsprogs 2.6.0 # xfs_db -V |
60 | o pcmciautils 001 | ||
60 | o pcmcia-cs 3.1.21 # cardmgr -V | 61 | o pcmcia-cs 3.1.21 # cardmgr -V |
61 | o quota-tools 3.09 # quota -V | 62 | o quota-tools 3.09 # quota -V |
62 | o PPP 2.4.0 # pppd --version | 63 | o PPP 2.4.0 # pppd --version |
@@ -186,13 +187,20 @@ architecture independent and any version from 2.0.0 onward should | |||
186 | work correctly with this version of the XFS kernel code (2.6.0 or | 187 | work correctly with this version of the XFS kernel code (2.6.0 or |
187 | later is recommended, due to some significant improvements). | 188 | later is recommended, due to some significant improvements). |
188 | 189 | ||
190 | PCMCIAutils | ||
191 | ----------- | ||
192 | |||
193 | PCMCIAutils replaces pcmcia-cs (see below). It properly sets up | ||
194 | PCMCIA sockets at system startup and loads the appropriate modules | ||
195 | for 16-bit PCMCIA devices if the kernel is modularized and the hotplug | ||
196 | subsystem is used. | ||
189 | 197 | ||
190 | Pcmcia-cs | 198 | Pcmcia-cs |
191 | --------- | 199 | --------- |
192 | 200 | ||
193 | PCMCIA (PC Card) support is now partially implemented in the main | 201 | PCMCIA (PC Card) support is now partially implemented in the main |
194 | kernel source. Pay attention when you recompile your kernel ;-). | 202 | kernel source. The "pcmciautils" package (see above) replaces pcmcia-cs |
195 | Also, be sure to upgrade to the latest pcmcia-cs release. | 203 | for newest kernels. |
196 | 204 | ||
197 | Quota-tools | 205 | Quota-tools |
198 | ----------- | 206 | ----------- |
@@ -349,9 +357,13 @@ Xfsprogs | |||
349 | -------- | 357 | -------- |
350 | o <ftp://oss.sgi.com/projects/xfs/download/> | 358 | o <ftp://oss.sgi.com/projects/xfs/download/> |
351 | 359 | ||
360 | Pcmciautils | ||
361 | ----------- | ||
362 | o <ftp://ftp.kernel.org/pub/linux/utils/kernel/pcmcia/> | ||
363 | |||
352 | Pcmcia-cs | 364 | Pcmcia-cs |
353 | --------- | 365 | --------- |
354 | o <ftp://pcmcia-cs.sourceforge.net/pub/pcmcia-cs/pcmcia-cs-3.1.21.tar.gz> | 366 | o <http://pcmcia-cs.sourceforge.net/> |
355 | 367 | ||
356 | Quota-tools | 368 | Quota-tools |
357 | ---------- | 369 | ---------- |
diff --git a/Documentation/pcmcia/devicetable.txt b/Documentation/pcmcia/devicetable.txt new file mode 100644 index 000000000000..045511acafc9 --- /dev/null +++ b/Documentation/pcmcia/devicetable.txt | |||
@@ -0,0 +1,64 @@ | |||
1 | Matching of PCMCIA devices to drivers is done using one or more of the | ||
2 | following criteria: | ||
3 | |||
4 | - manufactor ID | ||
5 | - card ID | ||
6 | - product ID strings _and_ hashes of these strings | ||
7 | - function ID | ||
8 | - device function (actual and pseudo) | ||
9 | |||
10 | You should use the helpers in include/pcmcia/device_id.h for generating the | ||
11 | struct pcmcia_device_id[] entries which match devices to drivers. | ||
12 | |||
13 | If you want to match product ID strings, you also need to pass the crc32 | ||
14 | hashes of the string to the macro, e.g. if you want to match the product ID | ||
15 | string 1, you need to use | ||
16 | |||
17 | PCMCIA_DEVICE_PROD_ID1("some_string", 0x(hash_of_some_string)), | ||
18 | |||
19 | If the hash is incorrect, the kernel will inform you about this in "dmesg" | ||
20 | upon module initialization, and tell you of the correct hash. | ||
21 | |||
22 | You can determine the hash of the product ID strings by running | ||
23 | "pcmcia-modalias %n.%m" [%n being replaced with the socket number and %m being | ||
24 | replaced with the device function] from pcmciautils. It generates a string | ||
25 | in the following form: | ||
26 | pcmcia:m0149cC1ABf06pfn00fn00pa725B842DpbF1EFEE84pc0877B627pd00000000 | ||
27 | |||
28 | The hex value after "pa" is the hash of product ID string 1, after "pb" for | ||
29 | string 2 and so on. | ||
30 | |||
31 | Alternatively, you can use this small tool to determine the crc32 hash. | ||
32 | simply pass the string you want to evaluate as argument to this program, | ||
33 | e.g. | ||
34 | $ ./crc32hash "Dual Speed" | ||
35 | |||
36 | ------------------------------------------------------------------------- | ||
37 | /* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */ | ||
38 | #include <string.h> | ||
39 | #include <stdio.h> | ||
40 | #include <ctype.h> | ||
41 | #include <stdlib.h> | ||
42 | |||
43 | unsigned int crc32(unsigned char const *p, unsigned int len) | ||
44 | { | ||
45 | int i; | ||
46 | unsigned int crc = 0; | ||
47 | while (len--) { | ||
48 | crc ^= *p++; | ||
49 | for (i = 0; i < 8; i++) | ||
50 | crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); | ||
51 | } | ||
52 | return crc; | ||
53 | } | ||
54 | |||
55 | int main(int argc, char **argv) { | ||
56 | unsigned int result; | ||
57 | if (argc != 2) { | ||
58 | printf("no string passed as argument\n"); | ||
59 | return -1; | ||
60 | } | ||
61 | result = crc32(argv[1], strlen(argv[1])); | ||
62 | printf("0x%x\n", result); | ||
63 | return 0; | ||
64 | } | ||
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt new file mode 100644 index 000000000000..9c315ab48a02 --- /dev/null +++ b/Documentation/pcmcia/driver-changes.txt | |||
@@ -0,0 +1,51 @@ | |||
1 | This file details changes in 2.6 which affect PCMCIA card driver authors: | ||
2 | |||
3 | * in-kernel device<->driver matching | ||
4 | PCMCIA devices and their correct drivers can now be matched in | ||
5 | kernelspace. See 'devicetable.txt' for details. | ||
6 | |||
7 | * Device model integration (as of 2.6.11) | ||
8 | A struct pcmcia_device is registered with the device model core, | ||
9 | and can be used (e.g. for SET_NETDEV_DEV) by using | ||
10 | handle_to_dev(client_handle_t * handle). | ||
11 | |||
12 | * Convert internal I/O port addresses to unsigned long (as of 2.6.11) | ||
13 | ioaddr_t should be replaced by kio_addr_t in PCMCIA card drivers. | ||
14 | |||
15 | * irq_mask and irq_list parameters (as of 2.6.11) | ||
16 | The irq_mask and irq_list parameters should no longer be used in | ||
17 | PCMCIA card drivers. Instead, it is the job of the PCMCIA core to | ||
18 | determine which IRQ should be used. Therefore, link->irq.IRQInfo2 | ||
19 | is ignored. | ||
20 | |||
21 | * client->PendingEvents is gone (as of 2.6.11) | ||
22 | client->PendingEvents is no longer available. | ||
23 | |||
24 | * client->Attributes are gone (as of 2.6.11) | ||
25 | client->Attributes is unused, therefore it is removed from all | ||
26 | PCMCIA card drivers | ||
27 | |||
28 | * core functions no longer available (as of 2.6.11) | ||
29 | The following functions have been removed from the kernel source | ||
30 | because they are unused by all in-kernel drivers, and no external | ||
31 | driver was reported to rely on them: | ||
32 | pcmcia_get_first_region() | ||
33 | pcmcia_get_next_region() | ||
34 | pcmcia_modify_window() | ||
35 | pcmcia_set_event_mask() | ||
36 | pcmcia_get_first_window() | ||
37 | pcmcia_get_next_window() | ||
38 | |||
39 | * device list iteration upon module removal (as of 2.6.10) | ||
40 | It is no longer necessary to iterate on the driver's internal | ||
41 | client list and call the ->detach() function upon module removal. | ||
42 | |||
43 | * Resource management. (as of 2.6.8) | ||
44 | Although the PCMCIA subsystem will allocate resources for cards, | ||
45 | it no longer marks these resources busy. This means that driver | ||
46 | authors are now responsible for claiming your resources as per | ||
47 | other drivers in Linux. You should use request_region() to mark | ||
48 | your IO regions in-use, and request_mem_region() to mark your | ||
49 | memory regions in-use. The name argument should be a pointer to | ||
50 | your driver name. Eg, for pcnet_cs, name should point to the | ||
51 | string "pcnet_cs". | ||
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index a0716ccc2f4a..8852c20c8d99 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <asm/ebus.h> | 16 | #include <asm/ebus.h> |
17 | #include <asm/auxio.h> | 17 | #include <asm/auxio.h> |
18 | 18 | ||
19 | /* This cannot be static, as it is referenced in entry.S */ | 19 | /* This cannot be static, as it is referenced in irq.c */ |
20 | void __iomem *auxio_register = NULL; | 20 | void __iomem *auxio_register = NULL; |
21 | 21 | ||
22 | enum auxio_type { | 22 | enum auxio_type { |
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index a47f2d0b1a29..eee516a71c14 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S | |||
@@ -271,8 +271,9 @@ cplus_fptrap_insn_1: | |||
271 | fmuld %f0, %f2, %f26 | 271 | fmuld %f0, %f2, %f26 |
272 | faddd %f0, %f2, %f28 | 272 | faddd %f0, %f2, %f28 |
273 | fmuld %f0, %f2, %f30 | 273 | fmuld %f0, %f2, %f30 |
274 | membar #Sync | ||
274 | b,pt %xcc, fpdis_exit | 275 | b,pt %xcc, fpdis_exit |
275 | membar #Sync | 276 | nop |
276 | 2: andcc %g5, FPRS_DU, %g0 | 277 | 2: andcc %g5, FPRS_DU, %g0 |
277 | bne,pt %icc, 3f | 278 | bne,pt %icc, 3f |
278 | fzero %f32 | 279 | fzero %f32 |
@@ -301,8 +302,9 @@ cplus_fptrap_insn_2: | |||
301 | fmuld %f32, %f34, %f58 | 302 | fmuld %f32, %f34, %f58 |
302 | faddd %f32, %f34, %f60 | 303 | faddd %f32, %f34, %f60 |
303 | fmuld %f32, %f34, %f62 | 304 | fmuld %f32, %f34, %f62 |
305 | membar #Sync | ||
304 | ba,pt %xcc, fpdis_exit | 306 | ba,pt %xcc, fpdis_exit |
305 | membar #Sync | 307 | nop |
306 | 3: mov SECONDARY_CONTEXT, %g3 | 308 | 3: mov SECONDARY_CONTEXT, %g3 |
307 | add %g6, TI_FPREGS, %g1 | 309 | add %g6, TI_FPREGS, %g1 |
308 | ldxa [%g3] ASI_DMMU, %g5 | 310 | ldxa [%g3] ASI_DMMU, %g5 |
@@ -699,116 +701,6 @@ utrap_ill: | |||
699 | ba,pt %xcc, rtrap | 701 | ba,pt %xcc, rtrap |
700 | clr %l6 | 702 | clr %l6 |
701 | 703 | ||
702 | #ifdef CONFIG_BLK_DEV_FD | ||
703 | .globl floppy_hardint | ||
704 | floppy_hardint: | ||
705 | wr %g0, (1 << 11), %clear_softint | ||
706 | sethi %hi(doing_pdma), %g1 | ||
707 | ld [%g1 + %lo(doing_pdma)], %g2 | ||
708 | brz,pn %g2, floppy_dosoftint | ||
709 | sethi %hi(fdc_status), %g3 | ||
710 | ldx [%g3 + %lo(fdc_status)], %g3 | ||
711 | sethi %hi(pdma_vaddr), %g5 | ||
712 | ldx [%g5 + %lo(pdma_vaddr)], %g4 | ||
713 | sethi %hi(pdma_size), %g5 | ||
714 | ldx [%g5 + %lo(pdma_size)], %g5 | ||
715 | |||
716 | next_byte: | ||
717 | lduba [%g3] ASI_PHYS_BYPASS_EC_E, %g7 | ||
718 | andcc %g7, 0x80, %g0 | ||
719 | be,pn %icc, floppy_fifo_emptied | ||
720 | andcc %g7, 0x20, %g0 | ||
721 | be,pn %icc, floppy_overrun | ||
722 | andcc %g7, 0x40, %g0 | ||
723 | be,pn %icc, floppy_write | ||
724 | sub %g5, 1, %g5 | ||
725 | |||
726 | inc %g3 | ||
727 | lduba [%g3] ASI_PHYS_BYPASS_EC_E, %g7 | ||
728 | dec %g3 | ||
729 | orcc %g0, %g5, %g0 | ||
730 | stb %g7, [%g4] | ||
731 | bne,pn %xcc, next_byte | ||
732 | add %g4, 1, %g4 | ||
733 | |||
734 | b,pt %xcc, floppy_tdone | ||
735 | nop | ||
736 | |||
737 | floppy_write: | ||
738 | ldub [%g4], %g7 | ||
739 | orcc %g0, %g5, %g0 | ||
740 | inc %g3 | ||
741 | stba %g7, [%g3] ASI_PHYS_BYPASS_EC_E | ||
742 | dec %g3 | ||
743 | bne,pn %xcc, next_byte | ||
744 | add %g4, 1, %g4 | ||
745 | |||
746 | floppy_tdone: | ||
747 | sethi %hi(pdma_vaddr), %g1 | ||
748 | stx %g4, [%g1 + %lo(pdma_vaddr)] | ||
749 | sethi %hi(pdma_size), %g1 | ||
750 | stx %g5, [%g1 + %lo(pdma_size)] | ||
751 | sethi %hi(auxio_register), %g1 | ||
752 | ldx [%g1 + %lo(auxio_register)], %g7 | ||
753 | lduba [%g7] ASI_PHYS_BYPASS_EC_E, %g5 | ||
754 | or %g5, AUXIO_AUX1_FTCNT, %g5 | ||
755 | /* andn %g5, AUXIO_AUX1_MASK, %g5 */ | ||
756 | stba %g5, [%g7] ASI_PHYS_BYPASS_EC_E | ||
757 | andn %g5, AUXIO_AUX1_FTCNT, %g5 | ||
758 | /* andn %g5, AUXIO_AUX1_MASK, %g5 */ | ||
759 | |||
760 | nop; nop; nop; nop; nop; nop; | ||
761 | nop; nop; nop; nop; nop; nop; | ||
762 | |||
763 | stba %g5, [%g7] ASI_PHYS_BYPASS_EC_E | ||
764 | sethi %hi(doing_pdma), %g1 | ||
765 | b,pt %xcc, floppy_dosoftint | ||
766 | st %g0, [%g1 + %lo(doing_pdma)] | ||
767 | |||
768 | floppy_fifo_emptied: | ||
769 | sethi %hi(pdma_vaddr), %g1 | ||
770 | stx %g4, [%g1 + %lo(pdma_vaddr)] | ||
771 | sethi %hi(pdma_size), %g1 | ||
772 | stx %g5, [%g1 + %lo(pdma_size)] | ||
773 | sethi %hi(irq_action), %g1 | ||
774 | or %g1, %lo(irq_action), %g1 | ||
775 | ldx [%g1 + (11 << 3)], %g3 ! irqaction[floppy_irq] | ||
776 | ldx [%g3 + 0x08], %g4 ! action->flags>>48==ino | ||
777 | sethi %hi(ivector_table), %g3 | ||
778 | srlx %g4, 48, %g4 | ||
779 | or %g3, %lo(ivector_table), %g3 | ||
780 | sllx %g4, 5, %g4 | ||
781 | ldx [%g3 + %g4], %g4 ! &ivector_table[ino] | ||
782 | ldx [%g4 + 0x10], %g4 ! bucket->iclr | ||
783 | stwa %g0, [%g4] ASI_PHYS_BYPASS_EC_E ! ICLR_IDLE | ||
784 | membar #Sync ! probably not needed... | ||
785 | retry | ||
786 | |||
787 | floppy_overrun: | ||
788 | sethi %hi(pdma_vaddr), %g1 | ||
789 | stx %g4, [%g1 + %lo(pdma_vaddr)] | ||
790 | sethi %hi(pdma_size), %g1 | ||
791 | stx %g5, [%g1 + %lo(pdma_size)] | ||
792 | sethi %hi(doing_pdma), %g1 | ||
793 | st %g0, [%g1 + %lo(doing_pdma)] | ||
794 | |||
795 | floppy_dosoftint: | ||
796 | rdpr %pil, %g2 | ||
797 | wrpr %g0, 15, %pil | ||
798 | sethi %hi(109f), %g7 | ||
799 | b,pt %xcc, etrap_irq | ||
800 | 109: or %g7, %lo(109b), %g7 | ||
801 | |||
802 | mov 11, %o0 | ||
803 | mov 0, %o1 | ||
804 | call sparc_floppy_irq | ||
805 | add %sp, PTREGS_OFF, %o2 | ||
806 | |||
807 | b,pt %xcc, rtrap_irq | ||
808 | nop | ||
809 | |||
810 | #endif /* CONFIG_BLK_DEV_FD */ | ||
811 | |||
812 | /* XXX Here is stuff we still need to write... -DaveM XXX */ | 704 | /* XXX Here is stuff we still need to write... -DaveM XXX */ |
813 | .globl netbsd_syscall | 705 | .globl netbsd_syscall |
814 | netbsd_syscall: | 706 | netbsd_syscall: |
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 4dcb8af94090..424712577307 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | #include <asm/cache.h> | 38 | #include <asm/cache.h> |
39 | #include <asm/cpudata.h> | 39 | #include <asm/cpudata.h> |
40 | #include <asm/auxio.h> | ||
40 | 41 | ||
41 | #ifdef CONFIG_SMP | 42 | #ifdef CONFIG_SMP |
42 | static void distribute_irqs(void); | 43 | static void distribute_irqs(void); |
@@ -834,137 +835,65 @@ void handler_irq(int irq, struct pt_regs *regs) | |||
834 | } | 835 | } |
835 | 836 | ||
836 | #ifdef CONFIG_BLK_DEV_FD | 837 | #ifdef CONFIG_BLK_DEV_FD |
837 | extern void floppy_interrupt(int irq, void *dev_cookie, struct pt_regs *regs); | 838 | extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *);; |
838 | 839 | ||
839 | void sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs) | 840 | /* XXX No easy way to include asm/floppy.h XXX */ |
840 | { | 841 | extern unsigned char *pdma_vaddr; |
841 | struct irqaction *action = *(irq + irq_action); | 842 | extern unsigned long pdma_size; |
842 | struct ino_bucket *bucket; | 843 | extern volatile int doing_pdma; |
843 | int cpu = smp_processor_id(); | 844 | extern unsigned long fdc_status; |
844 | |||
845 | irq_enter(); | ||
846 | kstat_this_cpu.irqs[irq]++; | ||
847 | |||
848 | *(irq_work(cpu, irq)) = 0; | ||
849 | bucket = get_ino_in_irqaction(action) + ivector_table; | ||
850 | |||
851 | bucket->flags |= IBF_INPROGRESS; | ||
852 | |||
853 | floppy_interrupt(irq, dev_cookie, regs); | ||
854 | upa_writel(ICLR_IDLE, bucket->iclr); | ||
855 | |||
856 | bucket->flags &= ~IBF_INPROGRESS; | ||
857 | |||
858 | irq_exit(); | ||
859 | } | ||
860 | #endif | ||
861 | |||
862 | /* The following assumes that the branch lies before the place we | ||
863 | * are branching to. This is the case for a trap vector... | ||
864 | * You have been warned. | ||
865 | */ | ||
866 | #define SPARC_BRANCH(dest_addr, inst_addr) \ | ||
867 | (0x10800000 | ((((dest_addr)-(inst_addr))>>2)&0x3fffff)) | ||
868 | |||
869 | #define SPARC_NOP (0x01000000) | ||
870 | 845 | ||
871 | static void install_fast_irq(unsigned int cpu_irq, | 846 | irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs) |
872 | irqreturn_t (*handler)(int, void *, struct pt_regs *)) | ||
873 | { | 847 | { |
874 | extern unsigned long sparc64_ttable_tl0; | 848 | if (likely(doing_pdma)) { |
875 | unsigned long ttent = (unsigned long) &sparc64_ttable_tl0; | 849 | void __iomem *stat = (void __iomem *) fdc_status; |
876 | unsigned int *insns; | 850 | unsigned char *vaddr = pdma_vaddr; |
877 | 851 | unsigned long size = pdma_size; | |
878 | ttent += 0x820; | 852 | u8 val; |
879 | ttent += (cpu_irq - 1) << 5; | 853 | |
880 | insns = (unsigned int *) ttent; | 854 | while (size) { |
881 | insns[0] = SPARC_BRANCH(((unsigned long) handler), | 855 | val = readb(stat); |
882 | ((unsigned long)&insns[0])); | 856 | if (unlikely(!(val & 0x80))) { |
883 | insns[1] = SPARC_NOP; | 857 | pdma_vaddr = vaddr; |
884 | __asm__ __volatile__("membar #StoreStore; flush %0" : : "r" (ttent)); | 858 | pdma_size = size; |
885 | } | 859 | return IRQ_HANDLED; |
886 | 860 | } | |
887 | int request_fast_irq(unsigned int irq, | 861 | if (unlikely(!(val & 0x20))) { |
888 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | 862 | pdma_vaddr = vaddr; |
889 | unsigned long irqflags, const char *name, void *dev_id) | 863 | pdma_size = size; |
890 | { | 864 | doing_pdma = 0; |
891 | struct irqaction *action; | 865 | goto main_interrupt; |
892 | struct ino_bucket *bucket = __bucket(irq); | 866 | } |
893 | unsigned long flags; | 867 | if (val & 0x40) { |
894 | 868 | /* read */ | |
895 | /* No pil0 dummy buckets allowed here. */ | 869 | *vaddr++ = readb(stat + 1); |
896 | if (bucket < &ivector_table[0] || | 870 | } else { |
897 | bucket >= &ivector_table[NUM_IVECS]) { | 871 | unsigned char data = *vaddr++; |
898 | unsigned int *caller; | ||
899 | |||
900 | __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); | ||
901 | printk(KERN_CRIT "request_fast_irq: Old style IRQ registry attempt " | ||
902 | "from %p, irq %08x.\n", caller, irq); | ||
903 | return -EINVAL; | ||
904 | } | ||
905 | |||
906 | if (!handler) | ||
907 | return -EINVAL; | ||
908 | 872 | ||
909 | if ((bucket->pil == 0) || (bucket->pil == 14)) { | 873 | /* write */ |
910 | printk("request_fast_irq: Trying to register shared IRQ 0 or 14.\n"); | 874 | writeb(data, stat + 1); |
911 | return -EBUSY; | 875 | } |
912 | } | 876 | size--; |
877 | } | ||
913 | 878 | ||
914 | spin_lock_irqsave(&irq_action_lock, flags); | 879 | pdma_vaddr = vaddr; |
880 | pdma_size = size; | ||
915 | 881 | ||
916 | action = *(bucket->pil + irq_action); | 882 | /* Send Terminal Count pulse to floppy controller. */ |
917 | if (action) { | 883 | val = readb(auxio_register); |
918 | if (action->flags & SA_SHIRQ) | 884 | val |= AUXIO_AUX1_FTCNT; |
919 | panic("Trying to register fast irq when already shared.\n"); | 885 | writeb(val, auxio_register); |
920 | if (irqflags & SA_SHIRQ) | 886 | val &= AUXIO_AUX1_FTCNT; |
921 | panic("Trying to register fast irq as shared.\n"); | 887 | writeb(val, auxio_register); |
922 | printk("request_fast_irq: Trying to register yet already owned.\n"); | ||
923 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
924 | return -EBUSY; | ||
925 | } | ||
926 | 888 | ||
927 | /* | 889 | doing_pdma = 0; |
928 | * We do not check for SA_SAMPLE_RANDOM in this path. Neither do we | ||
929 | * support smp intr affinity in this path. | ||
930 | */ | ||
931 | if (irqflags & SA_STATIC_ALLOC) { | ||
932 | if (static_irq_count < MAX_STATIC_ALLOC) | ||
933 | action = &static_irqaction[static_irq_count++]; | ||
934 | else | ||
935 | printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed " | ||
936 | "using kmalloc\n", bucket->pil, name); | ||
937 | } | ||
938 | if (action == NULL) | ||
939 | action = (struct irqaction *)kmalloc(sizeof(struct irqaction), | ||
940 | GFP_ATOMIC); | ||
941 | if (!action) { | ||
942 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
943 | return -ENOMEM; | ||
944 | } | 890 | } |
945 | install_fast_irq(bucket->pil, handler); | ||
946 | 891 | ||
947 | bucket->irq_info = action; | 892 | main_interrupt: |
948 | bucket->flags |= IBF_ACTIVE; | 893 | return floppy_interrupt(irq, dev_cookie, regs); |
949 | |||
950 | action->handler = handler; | ||
951 | action->flags = irqflags; | ||
952 | action->dev_id = NULL; | ||
953 | action->name = name; | ||
954 | action->next = NULL; | ||
955 | put_ino_in_irqaction(action, irq); | ||
956 | put_smpaff_in_irqaction(action, CPU_MASK_NONE); | ||
957 | |||
958 | *(bucket->pil + irq_action) = action; | ||
959 | enable_irq(irq); | ||
960 | |||
961 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
962 | |||
963 | #ifdef CONFIG_SMP | ||
964 | distribute_irqs(); | ||
965 | #endif | ||
966 | return 0; | ||
967 | } | 894 | } |
895 | EXPORT_SYMBOL(sparc_floppy_irq); | ||
896 | #endif | ||
968 | 897 | ||
969 | /* We really don't need these at all on the Sparc. We only have | 898 | /* We really don't need these at all on the Sparc. We only have |
970 | * stubs here because they are exported to modules. | 899 | * stubs here because they are exported to modules. |
diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c index 63496c43fe17..a809e63f03ef 100644 --- a/arch/sparc64/kernel/semaphore.c +++ b/arch/sparc64/kernel/semaphore.c | |||
@@ -32,8 +32,9 @@ static __inline__ int __sem_update_count(struct semaphore *sem, int incr) | |||
32 | " add %1, %4, %1\n" | 32 | " add %1, %4, %1\n" |
33 | " cas [%3], %0, %1\n" | 33 | " cas [%3], %0, %1\n" |
34 | " cmp %0, %1\n" | 34 | " cmp %0, %1\n" |
35 | " membar #StoreLoad | #StoreStore\n" | ||
35 | " bne,pn %%icc, 1b\n" | 36 | " bne,pn %%icc, 1b\n" |
36 | " membar #StoreLoad | #StoreStore\n" | 37 | " nop\n" |
37 | : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) | 38 | : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) |
38 | : "r" (&sem->count), "r" (incr), "m" (sem->count) | 39 | : "r" (&sem->count), "r" (incr), "m" (sem->count) |
39 | : "cc"); | 40 | : "cc"); |
@@ -71,8 +72,9 @@ void up(struct semaphore *sem) | |||
71 | " cmp %%g1, %%g7\n" | 72 | " cmp %%g1, %%g7\n" |
72 | " bne,pn %%icc, 1b\n" | 73 | " bne,pn %%icc, 1b\n" |
73 | " addcc %%g7, 1, %%g0\n" | 74 | " addcc %%g7, 1, %%g0\n" |
75 | " membar #StoreLoad | #StoreStore\n" | ||
74 | " ble,pn %%icc, 3f\n" | 76 | " ble,pn %%icc, 3f\n" |
75 | " membar #StoreLoad | #StoreStore\n" | 77 | " nop\n" |
76 | "2:\n" | 78 | "2:\n" |
77 | " .subsection 2\n" | 79 | " .subsection 2\n" |
78 | "3: mov %0, %%g1\n" | 80 | "3: mov %0, %%g1\n" |
@@ -128,8 +130,9 @@ void __sched down(struct semaphore *sem) | |||
128 | " cmp %%g1, %%g7\n" | 130 | " cmp %%g1, %%g7\n" |
129 | " bne,pn %%icc, 1b\n" | 131 | " bne,pn %%icc, 1b\n" |
130 | " cmp %%g7, 1\n" | 132 | " cmp %%g7, 1\n" |
133 | " membar #StoreLoad | #StoreStore\n" | ||
131 | " bl,pn %%icc, 3f\n" | 134 | " bl,pn %%icc, 3f\n" |
132 | " membar #StoreLoad | #StoreStore\n" | 135 | " nop\n" |
133 | "2:\n" | 136 | "2:\n" |
134 | " .subsection 2\n" | 137 | " .subsection 2\n" |
135 | "3: mov %0, %%g1\n" | 138 | "3: mov %0, %%g1\n" |
@@ -233,8 +236,9 @@ int __sched down_interruptible(struct semaphore *sem) | |||
233 | " cmp %%g1, %%g7\n" | 236 | " cmp %%g1, %%g7\n" |
234 | " bne,pn %%icc, 1b\n" | 237 | " bne,pn %%icc, 1b\n" |
235 | " cmp %%g7, 1\n" | 238 | " cmp %%g7, 1\n" |
239 | " membar #StoreLoad | #StoreStore\n" | ||
236 | " bl,pn %%icc, 3f\n" | 240 | " bl,pn %%icc, 3f\n" |
237 | " membar #StoreLoad | #StoreStore\n" | 241 | " nop\n" |
238 | "2:\n" | 242 | "2:\n" |
239 | " .subsection 2\n" | 243 | " .subsection 2\n" |
240 | "3: mov %2, %%g1\n" | 244 | "3: mov %2, %%g1\n" |
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index e78cc53594fa..56cd96f4a5cd 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
@@ -227,7 +227,6 @@ EXPORT_SYMBOL(__flush_dcache_range); | |||
227 | 227 | ||
228 | EXPORT_SYMBOL(mostek_lock); | 228 | EXPORT_SYMBOL(mostek_lock); |
229 | EXPORT_SYMBOL(mstk48t02_regs); | 229 | EXPORT_SYMBOL(mstk48t02_regs); |
230 | EXPORT_SYMBOL(request_fast_irq); | ||
231 | #ifdef CONFIG_SUN_AUXIO | 230 | #ifdef CONFIG_SUN_AUXIO |
232 | EXPORT_SYMBOL(auxio_set_led); | 231 | EXPORT_SYMBOL(auxio_set_led); |
233 | EXPORT_SYMBOL(auxio_set_lte); | 232 | EXPORT_SYMBOL(auxio_set_lte); |
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 2c8f9344b4ee..3a145fc39cf2 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S | |||
@@ -98,8 +98,9 @@ startup_continue: | |||
98 | 98 | ||
99 | sethi %hi(prom_entry_lock), %g2 | 99 | sethi %hi(prom_entry_lock), %g2 |
100 | 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 | 100 | 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 |
101 | membar #StoreLoad | #StoreStore | ||
101 | brnz,pn %g1, 1b | 102 | brnz,pn %g1, 1b |
102 | membar #StoreLoad | #StoreStore | 103 | nop |
103 | 104 | ||
104 | sethi %hi(p1275buf), %g2 | 105 | sethi %hi(p1275buf), %g2 |
105 | or %g2, %lo(p1275buf), %g2 | 106 | or %g2, %lo(p1275buf), %g2 |
diff --git a/arch/sparc64/lib/U1memcpy.S b/arch/sparc64/lib/U1memcpy.S index da9b520c7189..bafd2fc07acb 100644 --- a/arch/sparc64/lib/U1memcpy.S +++ b/arch/sparc64/lib/U1memcpy.S | |||
@@ -87,14 +87,17 @@ | |||
87 | #define LOOP_CHUNK3(src, dest, len, branch_dest) \ | 87 | #define LOOP_CHUNK3(src, dest, len, branch_dest) \ |
88 | MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) | 88 | MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) |
89 | 89 | ||
90 | #define DO_SYNC membar #Sync; | ||
90 | #define STORE_SYNC(dest, fsrc) \ | 91 | #define STORE_SYNC(dest, fsrc) \ |
91 | EX_ST(STORE_BLK(%fsrc, %dest)); \ | 92 | EX_ST(STORE_BLK(%fsrc, %dest)); \ |
92 | add %dest, 0x40, %dest; | 93 | add %dest, 0x40, %dest; \ |
94 | DO_SYNC | ||
93 | 95 | ||
94 | #define STORE_JUMP(dest, fsrc, target) \ | 96 | #define STORE_JUMP(dest, fsrc, target) \ |
95 | EX_ST(STORE_BLK(%fsrc, %dest)); \ | 97 | EX_ST(STORE_BLK(%fsrc, %dest)); \ |
96 | add %dest, 0x40, %dest; \ | 98 | add %dest, 0x40, %dest; \ |
97 | ba,pt %xcc, target; | 99 | ba,pt %xcc, target; \ |
100 | nop; | ||
98 | 101 | ||
99 | #define FINISH_VISCHUNK(dest, f0, f1, left) \ | 102 | #define FINISH_VISCHUNK(dest, f0, f1, left) \ |
100 | subcc %left, 8, %left;\ | 103 | subcc %left, 8, %left;\ |
@@ -239,17 +242,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
239 | ba,pt %xcc, 1b+4 | 242 | ba,pt %xcc, 1b+4 |
240 | faligndata %f0, %f2, %f48 | 243 | faligndata %f0, %f2, %f48 |
241 | 1: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) | 244 | 1: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) |
242 | STORE_SYNC(o0, f48) membar #Sync | 245 | STORE_SYNC(o0, f48) |
243 | FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) | 246 | FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) |
244 | STORE_JUMP(o0, f48, 40f) membar #Sync | 247 | STORE_JUMP(o0, f48, 40f) |
245 | 2: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) | 248 | 2: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) |
246 | STORE_SYNC(o0, f48) membar #Sync | 249 | STORE_SYNC(o0, f48) |
247 | FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) | 250 | FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) |
248 | STORE_JUMP(o0, f48, 48f) membar #Sync | 251 | STORE_JUMP(o0, f48, 48f) |
249 | 3: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) | 252 | 3: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) |
250 | STORE_SYNC(o0, f48) membar #Sync | 253 | STORE_SYNC(o0, f48) |
251 | FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) | 254 | FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) |
252 | STORE_JUMP(o0, f48, 56f) membar #Sync | 255 | STORE_JUMP(o0, f48, 56f) |
253 | 256 | ||
254 | 1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) | 257 | 1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) |
255 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) | 258 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) |
@@ -260,17 +263,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
260 | ba,pt %xcc, 1b+4 | 263 | ba,pt %xcc, 1b+4 |
261 | faligndata %f2, %f4, %f48 | 264 | faligndata %f2, %f4, %f48 |
262 | 1: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) | 265 | 1: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) |
263 | STORE_SYNC(o0, f48) membar #Sync | 266 | STORE_SYNC(o0, f48) |
264 | FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) | 267 | FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) |
265 | STORE_JUMP(o0, f48, 41f) membar #Sync | 268 | STORE_JUMP(o0, f48, 41f) |
266 | 2: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) | 269 | 2: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) |
267 | STORE_SYNC(o0, f48) membar #Sync | 270 | STORE_SYNC(o0, f48) |
268 | FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) | 271 | FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) |
269 | STORE_JUMP(o0, f48, 49f) membar #Sync | 272 | STORE_JUMP(o0, f48, 49f) |
270 | 3: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) | 273 | 3: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) |
271 | STORE_SYNC(o0, f48) membar #Sync | 274 | STORE_SYNC(o0, f48) |
272 | FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) | 275 | FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) |
273 | STORE_JUMP(o0, f48, 57f) membar #Sync | 276 | STORE_JUMP(o0, f48, 57f) |
274 | 277 | ||
275 | 1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) | 278 | 1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) |
276 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) | 279 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) |
@@ -281,17 +284,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
281 | ba,pt %xcc, 1b+4 | 284 | ba,pt %xcc, 1b+4 |
282 | faligndata %f4, %f6, %f48 | 285 | faligndata %f4, %f6, %f48 |
283 | 1: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) | 286 | 1: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) |
284 | STORE_SYNC(o0, f48) membar #Sync | 287 | STORE_SYNC(o0, f48) |
285 | FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) | 288 | FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) |
286 | STORE_JUMP(o0, f48, 42f) membar #Sync | 289 | STORE_JUMP(o0, f48, 42f) |
287 | 2: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) | 290 | 2: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) |
288 | STORE_SYNC(o0, f48) membar #Sync | 291 | STORE_SYNC(o0, f48) |
289 | FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) | 292 | FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) |
290 | STORE_JUMP(o0, f48, 50f) membar #Sync | 293 | STORE_JUMP(o0, f48, 50f) |
291 | 3: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) | 294 | 3: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) |
292 | STORE_SYNC(o0, f48) membar #Sync | 295 | STORE_SYNC(o0, f48) |
293 | FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) | 296 | FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) |
294 | STORE_JUMP(o0, f48, 58f) membar #Sync | 297 | STORE_JUMP(o0, f48, 58f) |
295 | 298 | ||
296 | 1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) | 299 | 1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) |
297 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) | 300 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) |
@@ -302,17 +305,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
302 | ba,pt %xcc, 1b+4 | 305 | ba,pt %xcc, 1b+4 |
303 | faligndata %f6, %f8, %f48 | 306 | faligndata %f6, %f8, %f48 |
304 | 1: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) | 307 | 1: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) |
305 | STORE_SYNC(o0, f48) membar #Sync | 308 | STORE_SYNC(o0, f48) |
306 | FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) | 309 | FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) |
307 | STORE_JUMP(o0, f48, 43f) membar #Sync | 310 | STORE_JUMP(o0, f48, 43f) |
308 | 2: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) | 311 | 2: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) |
309 | STORE_SYNC(o0, f48) membar #Sync | 312 | STORE_SYNC(o0, f48) |
310 | FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) | 313 | FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) |
311 | STORE_JUMP(o0, f48, 51f) membar #Sync | 314 | STORE_JUMP(o0, f48, 51f) |
312 | 3: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) | 315 | 3: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) |
313 | STORE_SYNC(o0, f48) membar #Sync | 316 | STORE_SYNC(o0, f48) |
314 | FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) | 317 | FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) |
315 | STORE_JUMP(o0, f48, 59f) membar #Sync | 318 | STORE_JUMP(o0, f48, 59f) |
316 | 319 | ||
317 | 1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) | 320 | 1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) |
318 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) | 321 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) |
@@ -323,17 +326,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
323 | ba,pt %xcc, 1b+4 | 326 | ba,pt %xcc, 1b+4 |
324 | faligndata %f8, %f10, %f48 | 327 | faligndata %f8, %f10, %f48 |
325 | 1: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) | 328 | 1: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) |
326 | STORE_SYNC(o0, f48) membar #Sync | 329 | STORE_SYNC(o0, f48) |
327 | FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) | 330 | FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) |
328 | STORE_JUMP(o0, f48, 44f) membar #Sync | 331 | STORE_JUMP(o0, f48, 44f) |
329 | 2: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) | 332 | 2: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) |
330 | STORE_SYNC(o0, f48) membar #Sync | 333 | STORE_SYNC(o0, f48) |
331 | FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) | 334 | FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) |
332 | STORE_JUMP(o0, f48, 52f) membar #Sync | 335 | STORE_JUMP(o0, f48, 52f) |
333 | 3: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) | 336 | 3: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) |
334 | STORE_SYNC(o0, f48) membar #Sync | 337 | STORE_SYNC(o0, f48) |
335 | FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) | 338 | FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) |
336 | STORE_JUMP(o0, f48, 60f) membar #Sync | 339 | STORE_JUMP(o0, f48, 60f) |
337 | 340 | ||
338 | 1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) | 341 | 1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) |
339 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) | 342 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) |
@@ -344,17 +347,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
344 | ba,pt %xcc, 1b+4 | 347 | ba,pt %xcc, 1b+4 |
345 | faligndata %f10, %f12, %f48 | 348 | faligndata %f10, %f12, %f48 |
346 | 1: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) | 349 | 1: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) |
347 | STORE_SYNC(o0, f48) membar #Sync | 350 | STORE_SYNC(o0, f48) |
348 | FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) | 351 | FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) |
349 | STORE_JUMP(o0, f48, 45f) membar #Sync | 352 | STORE_JUMP(o0, f48, 45f) |
350 | 2: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) | 353 | 2: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) |
351 | STORE_SYNC(o0, f48) membar #Sync | 354 | STORE_SYNC(o0, f48) |
352 | FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) | 355 | FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) |
353 | STORE_JUMP(o0, f48, 53f) membar #Sync | 356 | STORE_JUMP(o0, f48, 53f) |
354 | 3: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) | 357 | 3: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) |
355 | STORE_SYNC(o0, f48) membar #Sync | 358 | STORE_SYNC(o0, f48) |
356 | FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) | 359 | FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) |
357 | STORE_JUMP(o0, f48, 61f) membar #Sync | 360 | STORE_JUMP(o0, f48, 61f) |
358 | 361 | ||
359 | 1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) | 362 | 1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) |
360 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) | 363 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) |
@@ -365,17 +368,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
365 | ba,pt %xcc, 1b+4 | 368 | ba,pt %xcc, 1b+4 |
366 | faligndata %f12, %f14, %f48 | 369 | faligndata %f12, %f14, %f48 |
367 | 1: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) | 370 | 1: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) |
368 | STORE_SYNC(o0, f48) membar #Sync | 371 | STORE_SYNC(o0, f48) |
369 | FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) | 372 | FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) |
370 | STORE_JUMP(o0, f48, 46f) membar #Sync | 373 | STORE_JUMP(o0, f48, 46f) |
371 | 2: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) | 374 | 2: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) |
372 | STORE_SYNC(o0, f48) membar #Sync | 375 | STORE_SYNC(o0, f48) |
373 | FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) | 376 | FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) |
374 | STORE_JUMP(o0, f48, 54f) membar #Sync | 377 | STORE_JUMP(o0, f48, 54f) |
375 | 3: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) | 378 | 3: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) |
376 | STORE_SYNC(o0, f48) membar #Sync | 379 | STORE_SYNC(o0, f48) |
377 | FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) | 380 | FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) |
378 | STORE_JUMP(o0, f48, 62f) membar #Sync | 381 | STORE_JUMP(o0, f48, 62f) |
379 | 382 | ||
380 | 1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) | 383 | 1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) |
381 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) | 384 | LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) |
@@ -386,17 +389,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ | |||
386 | ba,pt %xcc, 1b+4 | 389 | ba,pt %xcc, 1b+4 |
387 | faligndata %f14, %f16, %f48 | 390 | faligndata %f14, %f16, %f48 |
388 | 1: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) | 391 | 1: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) |
389 | STORE_SYNC(o0, f48) membar #Sync | 392 | STORE_SYNC(o0, f48) |
390 | FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) | 393 | FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) |
391 | STORE_JUMP(o0, f48, 47f) membar #Sync | 394 | STORE_JUMP(o0, f48, 47f) |
392 | 2: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) | 395 | 2: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) |
393 | STORE_SYNC(o0, f48) membar #Sync | 396 | STORE_SYNC(o0, f48) |
394 | FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) | 397 | FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) |
395 | STORE_JUMP(o0, f48, 55f) membar #Sync | 398 | STORE_JUMP(o0, f48, 55f) |
396 | 3: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) | 399 | 3: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) |
397 | STORE_SYNC(o0, f48) membar #Sync | 400 | STORE_SYNC(o0, f48) |
398 | FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) | 401 | FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) |
399 | STORE_JUMP(o0, f48, 63f) membar #Sync | 402 | STORE_JUMP(o0, f48, 63f) |
400 | 403 | ||
401 | 40: FINISH_VISCHUNK(o0, f0, f2, g3) | 404 | 40: FINISH_VISCHUNK(o0, f0, f2, g3) |
402 | 41: FINISH_VISCHUNK(o0, f2, f4, g3) | 405 | 41: FINISH_VISCHUNK(o0, f2, f4, g3) |
diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S index 65e328d600a8..4e18989bd602 100644 --- a/arch/sparc64/lib/VISsave.S +++ b/arch/sparc64/lib/VISsave.S | |||
@@ -72,7 +72,11 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 | |||
72 | 72 | ||
73 | stda %f48, [%g3 + %g1] ASI_BLK_P | 73 | stda %f48, [%g3 + %g1] ASI_BLK_P |
74 | 5: membar #Sync | 74 | 5: membar #Sync |
75 | jmpl %g7 + %g0, %g0 | 75 | ba,pt %xcc, 80f |
76 | nop | ||
77 | |||
78 | .align 32 | ||
79 | 80: jmpl %g7 + %g0, %g0 | ||
76 | nop | 80 | nop |
77 | 81 | ||
78 | 6: ldub [%g3 + TI_FPSAVED], %o5 | 82 | 6: ldub [%g3 + TI_FPSAVED], %o5 |
@@ -87,8 +91,11 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 | |||
87 | stda %f32, [%g2 + %g1] ASI_BLK_P | 91 | stda %f32, [%g2 + %g1] ASI_BLK_P |
88 | stda %f48, [%g3 + %g1] ASI_BLK_P | 92 | stda %f48, [%g3 + %g1] ASI_BLK_P |
89 | membar #Sync | 93 | membar #Sync |
90 | jmpl %g7 + %g0, %g0 | 94 | ba,pt %xcc, 80f |
95 | nop | ||
91 | 96 | ||
97 | .align 32 | ||
98 | 80: jmpl %g7 + %g0, %g0 | ||
92 | nop | 99 | nop |
93 | 100 | ||
94 | .align 32 | 101 | .align 32 |
@@ -126,6 +133,10 @@ VISenterhalf: | |||
126 | stda %f0, [%g2 + %g1] ASI_BLK_P | 133 | stda %f0, [%g2 + %g1] ASI_BLK_P |
127 | stda %f16, [%g3 + %g1] ASI_BLK_P | 134 | stda %f16, [%g3 + %g1] ASI_BLK_P |
128 | membar #Sync | 135 | membar #Sync |
136 | ba,pt %xcc, 4f | ||
137 | nop | ||
138 | |||
139 | .align 32 | ||
129 | 4: and %o5, FPRS_DU, %o5 | 140 | 4: and %o5, FPRS_DU, %o5 |
130 | jmpl %g7 + %g0, %g0 | 141 | jmpl %g7 + %g0, %g0 |
131 | wr %o5, FPRS_FEF, %fprs | 142 | wr %o5, FPRS_FEF, %fprs |
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S index e528b8d1a3e6..faf87c31598b 100644 --- a/arch/sparc64/lib/atomic.S +++ b/arch/sparc64/lib/atomic.S | |||
@@ -7,18 +7,6 @@ | |||
7 | #include <linux/config.h> | 7 | #include <linux/config.h> |
8 | #include <asm/asi.h> | 8 | #include <asm/asi.h> |
9 | 9 | ||
10 | /* On SMP we need to use memory barriers to ensure | ||
11 | * correct memory operation ordering, nop these out | ||
12 | * for uniprocessor. | ||
13 | */ | ||
14 | #ifdef CONFIG_SMP | ||
15 | #define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad | ||
16 | #define ATOMIC_POST_BARRIER membar #StoreLoad | #StoreStore | ||
17 | #else | ||
18 | #define ATOMIC_PRE_BARRIER nop | ||
19 | #define ATOMIC_POST_BARRIER nop | ||
20 | #endif | ||
21 | |||
22 | .text | 10 | .text |
23 | 11 | ||
24 | /* Two versions of the atomic routines, one that | 12 | /* Two versions of the atomic routines, one that |
@@ -52,6 +40,24 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ | |||
52 | nop | 40 | nop |
53 | .size atomic_sub, .-atomic_sub | 41 | .size atomic_sub, .-atomic_sub |
54 | 42 | ||
43 | /* On SMP we need to use memory barriers to ensure | ||
44 | * correct memory operation ordering, nop these out | ||
45 | * for uniprocessor. | ||
46 | */ | ||
47 | #ifdef CONFIG_SMP | ||
48 | |||
49 | #define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad; | ||
50 | #define ATOMIC_POST_BARRIER \ | ||
51 | ba,pt %xcc, 80b; \ | ||
52 | membar #StoreLoad | #StoreStore | ||
53 | |||
54 | 80: retl | ||
55 | nop | ||
56 | #else | ||
57 | #define ATOMIC_PRE_BARRIER | ||
58 | #define ATOMIC_POST_BARRIER | ||
59 | #endif | ||
60 | |||
55 | .globl atomic_add_ret | 61 | .globl atomic_add_ret |
56 | .type atomic_add_ret,#function | 62 | .type atomic_add_ret,#function |
57 | atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ | 63 | atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ |
@@ -62,9 +68,10 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ | |||
62 | cmp %g1, %g7 | 68 | cmp %g1, %g7 |
63 | bne,pn %icc, 1b | 69 | bne,pn %icc, 1b |
64 | add %g7, %o0, %g7 | 70 | add %g7, %o0, %g7 |
71 | sra %g7, 0, %o0 | ||
65 | ATOMIC_POST_BARRIER | 72 | ATOMIC_POST_BARRIER |
66 | retl | 73 | retl |
67 | sra %g7, 0, %o0 | 74 | nop |
68 | .size atomic_add_ret, .-atomic_add_ret | 75 | .size atomic_add_ret, .-atomic_add_ret |
69 | 76 | ||
70 | .globl atomic_sub_ret | 77 | .globl atomic_sub_ret |
@@ -77,9 +84,10 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ | |||
77 | cmp %g1, %g7 | 84 | cmp %g1, %g7 |
78 | bne,pn %icc, 1b | 85 | bne,pn %icc, 1b |
79 | sub %g7, %o0, %g7 | 86 | sub %g7, %o0, %g7 |
87 | sra %g7, 0, %o0 | ||
80 | ATOMIC_POST_BARRIER | 88 | ATOMIC_POST_BARRIER |
81 | retl | 89 | retl |
82 | sra %g7, 0, %o0 | 90 | nop |
83 | .size atomic_sub_ret, .-atomic_sub_ret | 91 | .size atomic_sub_ret, .-atomic_sub_ret |
84 | 92 | ||
85 | .globl atomic64_add | 93 | .globl atomic64_add |
@@ -118,9 +126,10 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ | |||
118 | cmp %g1, %g7 | 126 | cmp %g1, %g7 |
119 | bne,pn %xcc, 1b | 127 | bne,pn %xcc, 1b |
120 | add %g7, %o0, %g7 | 128 | add %g7, %o0, %g7 |
129 | mov %g7, %o0 | ||
121 | ATOMIC_POST_BARRIER | 130 | ATOMIC_POST_BARRIER |
122 | retl | 131 | retl |
123 | mov %g7, %o0 | 132 | nop |
124 | .size atomic64_add_ret, .-atomic64_add_ret | 133 | .size atomic64_add_ret, .-atomic64_add_ret |
125 | 134 | ||
126 | .globl atomic64_sub_ret | 135 | .globl atomic64_sub_ret |
@@ -133,7 +142,8 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ | |||
133 | cmp %g1, %g7 | 142 | cmp %g1, %g7 |
134 | bne,pn %xcc, 1b | 143 | bne,pn %xcc, 1b |
135 | sub %g7, %o0, %g7 | 144 | sub %g7, %o0, %g7 |
145 | mov %g7, %o0 | ||
136 | ATOMIC_POST_BARRIER | 146 | ATOMIC_POST_BARRIER |
137 | retl | 147 | retl |
138 | mov %g7, %o0 | 148 | nop |
139 | .size atomic64_sub_ret, .-atomic64_sub_ret | 149 | .size atomic64_sub_ret, .-atomic64_sub_ret |
diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S index 886dcd2b376a..31afbfe6c1e8 100644 --- a/arch/sparc64/lib/bitops.S +++ b/arch/sparc64/lib/bitops.S | |||
@@ -7,20 +7,26 @@ | |||
7 | #include <linux/config.h> | 7 | #include <linux/config.h> |
8 | #include <asm/asi.h> | 8 | #include <asm/asi.h> |
9 | 9 | ||
10 | .text | ||
11 | |||
10 | /* On SMP we need to use memory barriers to ensure | 12 | /* On SMP we need to use memory barriers to ensure |
11 | * correct memory operation ordering, nop these out | 13 | * correct memory operation ordering, nop these out |
12 | * for uniprocessor. | 14 | * for uniprocessor. |
13 | */ | 15 | */ |
16 | |||
14 | #ifdef CONFIG_SMP | 17 | #ifdef CONFIG_SMP |
15 | #define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad | 18 | #define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad |
16 | #define BITOP_POST_BARRIER membar #StoreLoad | #StoreStore | 19 | #define BITOP_POST_BARRIER \ |
20 | ba,pt %xcc, 80b; \ | ||
21 | membar #StoreLoad | #StoreStore | ||
22 | |||
23 | 80: retl | ||
24 | nop | ||
17 | #else | 25 | #else |
18 | #define BITOP_PRE_BARRIER nop | 26 | #define BITOP_PRE_BARRIER |
19 | #define BITOP_POST_BARRIER nop | 27 | #define BITOP_POST_BARRIER |
20 | #endif | 28 | #endif |
21 | 29 | ||
22 | .text | ||
23 | |||
24 | .globl test_and_set_bit | 30 | .globl test_and_set_bit |
25 | .type test_and_set_bit,#function | 31 | .type test_and_set_bit,#function |
26 | test_and_set_bit: /* %o0=nr, %o1=addr */ | 32 | test_and_set_bit: /* %o0=nr, %o1=addr */ |
@@ -37,10 +43,11 @@ test_and_set_bit: /* %o0=nr, %o1=addr */ | |||
37 | cmp %g7, %g1 | 43 | cmp %g7, %g1 |
38 | bne,pn %xcc, 1b | 44 | bne,pn %xcc, 1b |
39 | and %g7, %o2, %g2 | 45 | and %g7, %o2, %g2 |
40 | BITOP_POST_BARRIER | ||
41 | clr %o0 | 46 | clr %o0 |
47 | movrne %g2, 1, %o0 | ||
48 | BITOP_POST_BARRIER | ||
42 | retl | 49 | retl |
43 | movrne %g2, 1, %o0 | 50 | nop |
44 | .size test_and_set_bit, .-test_and_set_bit | 51 | .size test_and_set_bit, .-test_and_set_bit |
45 | 52 | ||
46 | .globl test_and_clear_bit | 53 | .globl test_and_clear_bit |
@@ -59,10 +66,11 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */ | |||
59 | cmp %g7, %g1 | 66 | cmp %g7, %g1 |
60 | bne,pn %xcc, 1b | 67 | bne,pn %xcc, 1b |
61 | and %g7, %o2, %g2 | 68 | and %g7, %o2, %g2 |
62 | BITOP_POST_BARRIER | ||
63 | clr %o0 | 69 | clr %o0 |
70 | movrne %g2, 1, %o0 | ||
71 | BITOP_POST_BARRIER | ||
64 | retl | 72 | retl |
65 | movrne %g2, 1, %o0 | 73 | nop |
66 | .size test_and_clear_bit, .-test_and_clear_bit | 74 | .size test_and_clear_bit, .-test_and_clear_bit |
67 | 75 | ||
68 | .globl test_and_change_bit | 76 | .globl test_and_change_bit |
@@ -81,10 +89,11 @@ test_and_change_bit: /* %o0=nr, %o1=addr */ | |||
81 | cmp %g7, %g1 | 89 | cmp %g7, %g1 |
82 | bne,pn %xcc, 1b | 90 | bne,pn %xcc, 1b |
83 | and %g7, %o2, %g2 | 91 | and %g7, %o2, %g2 |
84 | BITOP_POST_BARRIER | ||
85 | clr %o0 | 92 | clr %o0 |
93 | movrne %g2, 1, %o0 | ||
94 | BITOP_POST_BARRIER | ||
86 | retl | 95 | retl |
87 | movrne %g2, 1, %o0 | 96 | nop |
88 | .size test_and_change_bit, .-test_and_change_bit | 97 | .size test_and_change_bit, .-test_and_change_bit |
89 | 98 | ||
90 | .globl set_bit | 99 | .globl set_bit |
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c index c421e0c65325..f03344cf784e 100644 --- a/arch/sparc64/lib/debuglocks.c +++ b/arch/sparc64/lib/debuglocks.c | |||
@@ -252,8 +252,9 @@ wlock_again: | |||
252 | " andn %%g1, %%g3, %%g7\n" | 252 | " andn %%g1, %%g3, %%g7\n" |
253 | " casx [%0], %%g1, %%g7\n" | 253 | " casx [%0], %%g1, %%g7\n" |
254 | " cmp %%g1, %%g7\n" | 254 | " cmp %%g1, %%g7\n" |
255 | " membar #StoreLoad | #StoreStore\n" | ||
255 | " bne,pn %%xcc, 1b\n" | 256 | " bne,pn %%xcc, 1b\n" |
256 | " membar #StoreLoad | #StoreStore" | 257 | " nop" |
257 | : /* no outputs */ | 258 | : /* no outputs */ |
258 | : "r" (&(rw->lock)) | 259 | : "r" (&(rw->lock)) |
259 | : "g3", "g1", "g7", "cc", "memory"); | 260 | : "g3", "g1", "g7", "cc", "memory"); |
@@ -351,8 +352,9 @@ int _do_write_trylock (rwlock_t *rw, char *str) | |||
351 | " andn %%g1, %%g3, %%g7\n" | 352 | " andn %%g1, %%g3, %%g7\n" |
352 | " casx [%0], %%g1, %%g7\n" | 353 | " casx [%0], %%g1, %%g7\n" |
353 | " cmp %%g1, %%g7\n" | 354 | " cmp %%g1, %%g7\n" |
355 | " membar #StoreLoad | #StoreStore\n" | ||
354 | " bne,pn %%xcc, 1b\n" | 356 | " bne,pn %%xcc, 1b\n" |
355 | " membar #StoreLoad | #StoreStore" | 357 | " nop" |
356 | : /* no outputs */ | 358 | : /* no outputs */ |
357 | : "r" (&(rw->lock)) | 359 | : "r" (&(rw->lock)) |
358 | : "g3", "g1", "g7", "cc", "memory"); | 360 | : "g3", "g1", "g7", "cc", "memory"); |
diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S index 7e6fdaebedba..8ee288dd0afc 100644 --- a/arch/sparc64/lib/dec_and_lock.S +++ b/arch/sparc64/lib/dec_and_lock.S | |||
@@ -48,8 +48,9 @@ start_to_zero: | |||
48 | #endif | 48 | #endif |
49 | to_zero: | 49 | to_zero: |
50 | ldstub [%o1], %g3 | 50 | ldstub [%o1], %g3 |
51 | membar #StoreLoad | #StoreStore | ||
51 | brnz,pn %g3, spin_on_lock | 52 | brnz,pn %g3, spin_on_lock |
52 | membar #StoreLoad | #StoreStore | 53 | nop |
53 | loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */ | 54 | loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */ |
54 | cmp %g2, %g7 | 55 | cmp %g2, %g7 |
55 | 56 | ||
@@ -71,8 +72,9 @@ loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */ | |||
71 | nop | 72 | nop |
72 | spin_on_lock: | 73 | spin_on_lock: |
73 | ldub [%o1], %g3 | 74 | ldub [%o1], %g3 |
75 | membar #LoadLoad | ||
74 | brnz,pt %g3, spin_on_lock | 76 | brnz,pt %g3, spin_on_lock |
75 | membar #LoadLoad | 77 | nop |
76 | ba,pt %xcc, to_zero | 78 | ba,pt %xcc, to_zero |
77 | nop | 79 | nop |
78 | nop | 80 | nop |
diff --git a/arch/sparc64/lib/rwsem.S b/arch/sparc64/lib/rwsem.S index 174ff7b9164c..75f0e6b951d6 100644 --- a/arch/sparc64/lib/rwsem.S +++ b/arch/sparc64/lib/rwsem.S | |||
@@ -17,8 +17,9 @@ __down_read: | |||
17 | bne,pn %icc, 1b | 17 | bne,pn %icc, 1b |
18 | add %g7, 1, %g7 | 18 | add %g7, 1, %g7 |
19 | cmp %g7, 0 | 19 | cmp %g7, 0 |
20 | membar #StoreLoad | #StoreStore | ||
20 | bl,pn %icc, 3f | 21 | bl,pn %icc, 3f |
21 | membar #StoreLoad | #StoreStore | 22 | nop |
22 | 2: | 23 | 2: |
23 | retl | 24 | retl |
24 | nop | 25 | nop |
@@ -57,8 +58,9 @@ __down_write: | |||
57 | cmp %g3, %g7 | 58 | cmp %g3, %g7 |
58 | bne,pn %icc, 1b | 59 | bne,pn %icc, 1b |
59 | cmp %g7, 0 | 60 | cmp %g7, 0 |
61 | membar #StoreLoad | #StoreStore | ||
60 | bne,pn %icc, 3f | 62 | bne,pn %icc, 3f |
61 | membar #StoreLoad | #StoreStore | 63 | nop |
62 | 2: retl | 64 | 2: retl |
63 | nop | 65 | nop |
64 | 3: | 66 | 3: |
@@ -97,8 +99,9 @@ __up_read: | |||
97 | cmp %g1, %g7 | 99 | cmp %g1, %g7 |
98 | bne,pn %icc, 1b | 100 | bne,pn %icc, 1b |
99 | cmp %g7, 0 | 101 | cmp %g7, 0 |
102 | membar #StoreLoad | #StoreStore | ||
100 | bl,pn %icc, 3f | 103 | bl,pn %icc, 3f |
101 | membar #StoreLoad | #StoreStore | 104 | nop |
102 | 2: retl | 105 | 2: retl |
103 | nop | 106 | nop |
104 | 3: sethi %hi(RWSEM_ACTIVE_MASK), %g1 | 107 | 3: sethi %hi(RWSEM_ACTIVE_MASK), %g1 |
@@ -126,8 +129,9 @@ __up_write: | |||
126 | bne,pn %icc, 1b | 129 | bne,pn %icc, 1b |
127 | sub %g7, %g1, %g7 | 130 | sub %g7, %g1, %g7 |
128 | cmp %g7, 0 | 131 | cmp %g7, 0 |
132 | membar #StoreLoad | #StoreStore | ||
129 | bl,pn %icc, 3f | 133 | bl,pn %icc, 3f |
130 | membar #StoreLoad | #StoreStore | 134 | nop |
131 | 2: | 135 | 2: |
132 | retl | 136 | retl |
133 | nop | 137 | nop |
@@ -151,8 +155,9 @@ __downgrade_write: | |||
151 | bne,pn %icc, 1b | 155 | bne,pn %icc, 1b |
152 | sub %g7, %g1, %g7 | 156 | sub %g7, %g1, %g7 |
153 | cmp %g7, 0 | 157 | cmp %g7, 0 |
158 | membar #StoreLoad | #StoreStore | ||
154 | bl,pn %icc, 3f | 159 | bl,pn %icc, 3f |
155 | membar #StoreLoad | #StoreStore | 160 | nop |
156 | 2: | 161 | 2: |
157 | retl | 162 | retl |
158 | nop | 163 | nop |
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 9c5222075da9..8fc413cb6acd 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
@@ -136,8 +136,9 @@ static __inline__ void set_dcache_dirty(struct page *page, int this_cpu) | |||
136 | "or %%g1, %0, %%g1\n\t" | 136 | "or %%g1, %0, %%g1\n\t" |
137 | "casx [%2], %%g7, %%g1\n\t" | 137 | "casx [%2], %%g7, %%g1\n\t" |
138 | "cmp %%g7, %%g1\n\t" | 138 | "cmp %%g7, %%g1\n\t" |
139 | "membar #StoreLoad | #StoreStore\n\t" | ||
139 | "bne,pn %%xcc, 1b\n\t" | 140 | "bne,pn %%xcc, 1b\n\t" |
140 | " membar #StoreLoad | #StoreStore" | 141 | " nop" |
141 | : /* no outputs */ | 142 | : /* no outputs */ |
142 | : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags) | 143 | : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags) |
143 | : "g1", "g7"); | 144 | : "g1", "g7"); |
@@ -157,8 +158,9 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c | |||
157 | " andn %%g7, %1, %%g1\n\t" | 158 | " andn %%g7, %1, %%g1\n\t" |
158 | "casx [%2], %%g7, %%g1\n\t" | 159 | "casx [%2], %%g7, %%g1\n\t" |
159 | "cmp %%g7, %%g1\n\t" | 160 | "cmp %%g7, %%g1\n\t" |
161 | "membar #StoreLoad | #StoreStore\n\t" | ||
160 | "bne,pn %%xcc, 1b\n\t" | 162 | "bne,pn %%xcc, 1b\n\t" |
161 | " membar #StoreLoad | #StoreStore\n" | 163 | " nop\n" |
162 | "2:" | 164 | "2:" |
163 | : /* no outputs */ | 165 | : /* no outputs */ |
164 | : "r" (cpu), "r" (mask), "r" (&page->flags), | 166 | : "r" (cpu), "r" (mask), "r" (&page->flags), |
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index 7a0934321010..7a2431d3abc7 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S | |||
@@ -266,8 +266,9 @@ __cheetah_flush_tlb_pending: /* 22 insns */ | |||
266 | andn %o3, 1, %o3 | 266 | andn %o3, 1, %o3 |
267 | stxa %g0, [%o3] ASI_IMMU_DEMAP | 267 | stxa %g0, [%o3] ASI_IMMU_DEMAP |
268 | 2: stxa %g0, [%o3] ASI_DMMU_DEMAP | 268 | 2: stxa %g0, [%o3] ASI_DMMU_DEMAP |
269 | membar #Sync | ||
269 | brnz,pt %o1, 1b | 270 | brnz,pt %o1, 1b |
270 | membar #Sync | 271 | nop |
271 | stxa %g2, [%o4] ASI_DMMU | 272 | stxa %g2, [%o4] ASI_DMMU |
272 | flush %g6 | 273 | flush %g6 |
273 | wrpr %g0, 0, %tl | 274 | wrpr %g0, 0, %tl |
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index ff1cc968f96d..de5746e38af9 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c | |||
@@ -300,7 +300,6 @@ CFQ_CRQ_FNS(requeued); | |||
300 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); | 300 | static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); |
301 | static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *); | 301 | static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *); |
302 | static void cfq_put_cfqd(struct cfq_data *cfqd); | 302 | static void cfq_put_cfqd(struct cfq_data *cfqd); |
303 | static inline int cfq_pending_requests(struct cfq_data *cfqd); | ||
304 | 303 | ||
305 | #define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) | 304 | #define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) |
306 | 305 | ||
@@ -348,6 +347,28 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) | |||
348 | return NULL; | 347 | return NULL; |
349 | } | 348 | } |
350 | 349 | ||
350 | static inline int cfq_pending_requests(struct cfq_data *cfqd) | ||
351 | { | ||
352 | return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues; | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * scheduler run of queue, if there are requests pending and no one in the | ||
357 | * driver that will restart queueing | ||
358 | */ | ||
359 | static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) | ||
360 | { | ||
361 | if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd)) | ||
362 | kblockd_schedule_work(&cfqd->unplug_work); | ||
363 | } | ||
364 | |||
365 | static int cfq_queue_empty(request_queue_t *q) | ||
366 | { | ||
367 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
368 | |||
369 | return !cfq_pending_requests(cfqd); | ||
370 | } | ||
371 | |||
351 | /* | 372 | /* |
352 | * Lifted from AS - choose which of crq1 and crq2 that is best served now. | 373 | * Lifted from AS - choose which of crq1 and crq2 that is best served now. |
353 | * We choose the request that is closest to the head right now. Distance | 374 | * We choose the request that is closest to the head right now. Distance |
@@ -1072,16 +1093,6 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
1072 | } | 1093 | } |
1073 | 1094 | ||
1074 | /* | 1095 | /* |
1075 | * scheduler run of queue, if there are requests pending and no one in the | ||
1076 | * driver that will restart queueing | ||
1077 | */ | ||
1078 | static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) | ||
1079 | { | ||
1080 | if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd)) | ||
1081 | kblockd_schedule_work(&cfqd->unplug_work); | ||
1082 | } | ||
1083 | |||
1084 | /* | ||
1085 | * get next queue for service | 1096 | * get next queue for service |
1086 | */ | 1097 | */ |
1087 | static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) | 1098 | static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) |
@@ -1846,18 +1857,6 @@ cfq_insert_request(request_queue_t *q, struct request *rq, int where) | |||
1846 | } | 1857 | } |
1847 | } | 1858 | } |
1848 | 1859 | ||
1849 | static inline int cfq_pending_requests(struct cfq_data *cfqd) | ||
1850 | { | ||
1851 | return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues; | ||
1852 | } | ||
1853 | |||
1854 | static int cfq_queue_empty(request_queue_t *q) | ||
1855 | { | ||
1856 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
1857 | |||
1858 | return !cfq_pending_requests(cfqd); | ||
1859 | } | ||
1860 | |||
1861 | static void cfq_completed_request(request_queue_t *q, struct request *rq) | 1860 | static void cfq_completed_request(request_queue_t *q, struct request *rq) |
1862 | { | 1861 | { |
1863 | struct cfq_rq *crq = RQ_DATA(rq); | 1862 | struct cfq_rq *crq = RQ_DATA(rq); |
@@ -1952,7 +1951,7 @@ __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1952 | { | 1951 | { |
1953 | #if 1 | 1952 | #if 1 |
1954 | if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && | 1953 | if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && |
1955 | !cfq_cfqq_must_alloc_slice) { | 1954 | !cfq_cfqq_must_alloc_slice(cfqq)) { |
1956 | cfq_mark_cfqq_must_alloc_slice(cfqq); | 1955 | cfq_mark_cfqq_must_alloc_slice(cfqq); |
1957 | return ELV_MQUEUE_MUST; | 1956 | return ELV_MQUEUE_MUST; |
1958 | } | 1957 | } |
@@ -1969,7 +1968,7 @@ __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1969 | * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we | 1968 | * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we |
1970 | * can quickly flood the queue with writes from a single task | 1969 | * can quickly flood the queue with writes from a single task |
1971 | */ | 1970 | */ |
1972 | if (rw == READ || !cfq_cfqq_must_alloc_slice) { | 1971 | if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) { |
1973 | cfq_mark_cfqq_must_alloc_slice(cfqq); | 1972 | cfq_mark_cfqq_must_alloc_slice(cfqq); |
1974 | return ELV_MQUEUE_MUST; | 1973 | return ELV_MQUEUE_MUST; |
1975 | } | 1974 | } |
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index e481cc411b5d..5ef9adb9fe73 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -1089,6 +1089,14 @@ static int bluecard_event(event_t event, int priority, event_callback_args_t *ar | |||
1089 | return 0; | 1089 | return 0; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | static struct pcmcia_device_id bluecard_ids[] = { | ||
1093 | PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e), | ||
1094 | PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c), | ||
1095 | PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab), | ||
1096 | PCMCIA_DEVICE_NULL | ||
1097 | }; | ||
1098 | MODULE_DEVICE_TABLE(pcmcia, bluecard_ids); | ||
1099 | |||
1092 | static struct pcmcia_driver bluecard_driver = { | 1100 | static struct pcmcia_driver bluecard_driver = { |
1093 | .owner = THIS_MODULE, | 1101 | .owner = THIS_MODULE, |
1094 | .drv = { | 1102 | .drv = { |
@@ -1096,6 +1104,7 @@ static struct pcmcia_driver bluecard_driver = { | |||
1096 | }, | 1104 | }, |
1097 | .attach = bluecard_attach, | 1105 | .attach = bluecard_attach, |
1098 | .detach = bluecard_detach, | 1106 | .detach = bluecard_detach, |
1107 | .id_table = bluecard_ids, | ||
1099 | }; | 1108 | }; |
1100 | 1109 | ||
1101 | static int __init init_bluecard_cs(void) | 1110 | static int __init init_bluecard_cs(void) |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index f71e5c76963d..9013cd759afb 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -935,6 +935,12 @@ static int bt3c_event(event_t event, int priority, event_callback_args_t *args) | |||
935 | return 0; | 935 | return 0; |
936 | } | 936 | } |
937 | 937 | ||
938 | static struct pcmcia_device_id bt3c_ids[] = { | ||
939 | PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02), | ||
940 | PCMCIA_DEVICE_NULL | ||
941 | }; | ||
942 | MODULE_DEVICE_TABLE(pcmcia, bt3c_ids); | ||
943 | |||
938 | static struct pcmcia_driver bt3c_driver = { | 944 | static struct pcmcia_driver bt3c_driver = { |
939 | .owner = THIS_MODULE, | 945 | .owner = THIS_MODULE, |
940 | .drv = { | 946 | .drv = { |
@@ -942,6 +948,7 @@ static struct pcmcia_driver bt3c_driver = { | |||
942 | }, | 948 | }, |
943 | .attach = bt3c_attach, | 949 | .attach = bt3c_attach, |
944 | .detach = bt3c_detach, | 950 | .detach = bt3c_detach, |
951 | .id_table = bt3c_ids, | ||
945 | }; | 952 | }; |
946 | 953 | ||
947 | static int __init init_bt3c_cs(void) | 954 | static int __init init_bt3c_cs(void) |
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index ad8d972444a5..c479484a1f7f 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -855,6 +855,12 @@ static int btuart_event(event_t event, int priority, event_callback_args_t *args | |||
855 | return 0; | 855 | return 0; |
856 | } | 856 | } |
857 | 857 | ||
858 | static struct pcmcia_device_id btuart_ids[] = { | ||
859 | /* don't use this driver. Use serial_cs + hci_uart instead */ | ||
860 | PCMCIA_DEVICE_NULL | ||
861 | }; | ||
862 | MODULE_DEVICE_TABLE(pcmcia, btuart_ids); | ||
863 | |||
858 | static struct pcmcia_driver btuart_driver = { | 864 | static struct pcmcia_driver btuart_driver = { |
859 | .owner = THIS_MODULE, | 865 | .owner = THIS_MODULE, |
860 | .drv = { | 866 | .drv = { |
@@ -862,6 +868,7 @@ static struct pcmcia_driver btuart_driver = { | |||
862 | }, | 868 | }, |
863 | .attach = btuart_attach, | 869 | .attach = btuart_attach, |
864 | .detach = btuart_detach, | 870 | .detach = btuart_detach, |
871 | .id_table = btuart_ids, | ||
865 | }; | 872 | }; |
866 | 873 | ||
867 | static int __init init_btuart_cs(void) | 874 | static int __init init_btuart_cs(void) |
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index fe954e5d9a1d..bb12f7daeb91 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -807,6 +807,13 @@ static int dtl1_event(event_t event, int priority, event_callback_args_t *args) | |||
807 | return 0; | 807 | return 0; |
808 | } | 808 | } |
809 | 809 | ||
810 | static struct pcmcia_device_id dtl1_ids[] = { | ||
811 | PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), | ||
812 | PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), | ||
813 | PCMCIA_DEVICE_NULL | ||
814 | }; | ||
815 | MODULE_DEVICE_TABLE(pcmcia, dtl1_ids); | ||
816 | |||
810 | static struct pcmcia_driver dtl1_driver = { | 817 | static struct pcmcia_driver dtl1_driver = { |
811 | .owner = THIS_MODULE, | 818 | .owner = THIS_MODULE, |
812 | .drv = { | 819 | .drv = { |
@@ -814,6 +821,7 @@ static struct pcmcia_driver dtl1_driver = { | |||
814 | }, | 821 | }, |
815 | .attach = dtl1_attach, | 822 | .attach = dtl1_attach, |
816 | .detach = dtl1_detach, | 823 | .detach = dtl1_detach, |
824 | .id_table = dtl1_ids, | ||
817 | }; | 825 | }; |
818 | 826 | ||
819 | static int __init init_dtl1_cs(void) | 827 | static int __init init_dtl1_cs(void) |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 1c8d866a49dc..8f36b1758eb6 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -581,7 +581,7 @@ static dev_link_t *mgslpc_attach(void) | |||
581 | 581 | ||
582 | /* Interrupt setup */ | 582 | /* Interrupt setup */ |
583 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 583 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
584 | link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; | 584 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
585 | link->irq.Handler = NULL; | 585 | link->irq.Handler = NULL; |
586 | 586 | ||
587 | link->conf.Attributes = 0; | 587 | link->conf.Attributes = 0; |
@@ -3081,6 +3081,12 @@ void mgslpc_remove_device(MGSLPC_INFO *remove_info) | |||
3081 | } | 3081 | } |
3082 | } | 3082 | } |
3083 | 3083 | ||
3084 | static struct pcmcia_device_id mgslpc_ids[] = { | ||
3085 | PCMCIA_DEVICE_MANF_CARD(0x02c5, 0x0050), | ||
3086 | PCMCIA_DEVICE_NULL | ||
3087 | }; | ||
3088 | MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids); | ||
3089 | |||
3084 | static struct pcmcia_driver mgslpc_driver = { | 3090 | static struct pcmcia_driver mgslpc_driver = { |
3085 | .owner = THIS_MODULE, | 3091 | .owner = THIS_MODULE, |
3086 | .drv = { | 3092 | .drv = { |
@@ -3088,6 +3094,7 @@ static struct pcmcia_driver mgslpc_driver = { | |||
3088 | }, | 3094 | }, |
3089 | .attach = mgslpc_attach, | 3095 | .attach = mgslpc_attach, |
3090 | .detach = mgslpc_detach, | 3096 | .detach = mgslpc_detach, |
3097 | .id_table = mgslpc_ids, | ||
3091 | }; | 3098 | }; |
3092 | 3099 | ||
3093 | static struct tty_operations mgslpc_ops = { | 3100 | static struct tty_operations mgslpc_ops = { |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 0273f124a4f7..5f33df47aa74 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -606,6 +606,12 @@ config BLK_DEV_IT8172 | |||
606 | <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the | 606 | <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the |
607 | board at <http://www.mvista.com/partners/semiconductor/ite.html>. | 607 | board at <http://www.mvista.com/partners/semiconductor/ite.html>. |
608 | 608 | ||
609 | config BLK_DEV_IT821X | ||
610 | tristate "IT821X IDE support" | ||
611 | help | ||
612 | This driver adds support for the ITE 8211 IDE controller and the | ||
613 | IT 8212 IDE RAID controller in both RAID and pass-through mode. | ||
614 | |||
609 | config BLK_DEV_NS87415 | 615 | config BLK_DEV_NS87415 |
610 | tristate "NS87415 chipset support" | 616 | tristate "NS87415 chipset support" |
611 | help | 617 | help |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index d6f934886b04..f9c1acb4ed6a 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -119,6 +119,10 @@ static int lba_capacity_is_ok (struct hd_driveid *id) | |||
119 | { | 119 | { |
120 | unsigned long lba_sects, chs_sects, head, tail; | 120 | unsigned long lba_sects, chs_sects, head, tail; |
121 | 121 | ||
122 | /* No non-LBA info .. so valid! */ | ||
123 | if (id->cyls == 0) | ||
124 | return 1; | ||
125 | |||
122 | /* | 126 | /* |
123 | * The ATA spec tells large drives to return | 127 | * The ATA spec tells large drives to return |
124 | * C/H/S = 16383/16/63 independent of their size. | 128 | * C/H/S = 16383/16/63 independent of their size. |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 2d2eefb610dd..1e1531334c25 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
@@ -132,7 +132,6 @@ static const struct drive_list_entry drive_blacklist [] = { | |||
132 | { "SAMSUNG CD-ROM SC-148C", "ALL" }, | 132 | { "SAMSUNG CD-ROM SC-148C", "ALL" }, |
133 | { "SAMSUNG CD-ROM SC", "ALL" }, | 133 | { "SAMSUNG CD-ROM SC", "ALL" }, |
134 | { "SanDisk SDP3B-64" , "ALL" }, | 134 | { "SanDisk SDP3B-64" , "ALL" }, |
135 | { "SAMSUNG CD-ROM SN-124", "ALL" }, | ||
136 | { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, | 135 | { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, |
137 | { "_NEC DV5800A", "ALL" }, | 136 | { "_NEC DV5800A", "ALL" }, |
138 | { NULL , NULL } | 137 | { NULL , NULL } |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 53024942a7eb..b443b04a4c5a 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -1181,7 +1181,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | |||
1181 | pre_reset(drive); | 1181 | pre_reset(drive); |
1182 | SELECT_DRIVE(drive); | 1182 | SELECT_DRIVE(drive); |
1183 | udelay (20); | 1183 | udelay (20); |
1184 | hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); | 1184 | hwif->OUTBSYNC(drive, WIN_SRST, IDE_COMMAND_REG); |
1185 | ndelay(400); | ||
1185 | hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; | 1186 | hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; |
1186 | hwgroup->polling = 1; | 1187 | hwgroup->polling = 1; |
1187 | __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); | 1188 | __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); |
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index e20327e54b1a..978d27d6452d 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c | |||
@@ -457,6 +457,40 @@ int ide_event(event_t event, int priority, | |||
457 | return 0; | 457 | return 0; |
458 | } /* ide_event */ | 458 | } /* ide_event */ |
459 | 459 | ||
460 | static struct pcmcia_device_id ide_ids[] = { | ||
461 | PCMCIA_DEVICE_FUNC_ID(4), | ||
462 | PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), | ||
463 | PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), | ||
464 | PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), | ||
465 | PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), | ||
466 | PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), | ||
467 | PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74), | ||
468 | PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), | ||
469 | PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), | ||
470 | PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), | ||
471 | PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), | ||
472 | PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), | ||
473 | PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), | ||
474 | PCMCIA_DEVICE_PROD_ID12("EXP", "CD", 0x6f58c983, 0xaae5994f), | ||
475 | PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), | ||
476 | PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), | ||
477 | PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), | ||
478 | PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), | ||
479 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), | ||
480 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), | ||
481 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), | ||
482 | PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), | ||
483 | PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79), | ||
484 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), | ||
485 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), | ||
486 | PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), | ||
487 | PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), | ||
488 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), | ||
489 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), | ||
490 | PCMCIA_DEVICE_NULL, | ||
491 | }; | ||
492 | MODULE_DEVICE_TABLE(pcmcia, ide_ids); | ||
493 | |||
460 | static struct pcmcia_driver ide_cs_driver = { | 494 | static struct pcmcia_driver ide_cs_driver = { |
461 | .owner = THIS_MODULE, | 495 | .owner = THIS_MODULE, |
462 | .drv = { | 496 | .drv = { |
@@ -464,6 +498,7 @@ static struct pcmcia_driver ide_cs_driver = { | |||
464 | }, | 498 | }, |
465 | .attach = ide_attach, | 499 | .attach = ide_attach, |
466 | .detach = ide_detach, | 500 | .detach = ide_detach, |
501 | .id_table = ide_ids, | ||
467 | }; | 502 | }; |
468 | 503 | ||
469 | static int __init init_ide_cs(void) | 504 | static int __init init_ide_cs(void) |
diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index 55e6e553e497..af46226c1796 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o | |||
12 | obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o | 12 | obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o |
13 | #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o | 13 | #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o |
14 | obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o | 14 | obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o |
15 | obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o | ||
15 | obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o | 16 | obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o |
16 | obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o | 17 | obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o |
17 | obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o | 18 | obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o |
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 4565cc311ff3..da46577380f3 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c | |||
@@ -39,6 +39,17 @@ | |||
39 | 39 | ||
40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
41 | 41 | ||
42 | static int ide_generic_all; /* Set to claim all devices */ | ||
43 | |||
44 | static int __init ide_generic_all_on(char *unused) | ||
45 | { | ||
46 | ide_generic_all = 1; | ||
47 | printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n"); | ||
48 | return 1; | ||
49 | } | ||
50 | |||
51 | __setup("all-generic-ide", ide_generic_all_on); | ||
52 | |||
42 | static void __devinit init_hwif_generic (ide_hwif_t *hwif) | 53 | static void __devinit init_hwif_generic (ide_hwif_t *hwif) |
43 | { | 54 | { |
44 | switch(hwif->pci_dev->device) { | 55 | switch(hwif->pci_dev->device) { |
@@ -78,79 +89,85 @@ static void __devinit init_hwif_generic (ide_hwif_t *hwif) | |||
78 | 89 | ||
79 | static ide_pci_device_t generic_chipsets[] __devinitdata = { | 90 | static ide_pci_device_t generic_chipsets[] __devinitdata = { |
80 | { /* 0 */ | 91 | { /* 0 */ |
92 | .name = "Unknown", | ||
93 | .init_hwif = init_hwif_generic, | ||
94 | .channels = 2, | ||
95 | .autodma = AUTODMA, | ||
96 | .bootable = ON_BOARD, | ||
97 | },{ /* 1 */ | ||
81 | .name = "NS87410", | 98 | .name = "NS87410", |
82 | .init_hwif = init_hwif_generic, | 99 | .init_hwif = init_hwif_generic, |
83 | .channels = 2, | 100 | .channels = 2, |
84 | .autodma = AUTODMA, | 101 | .autodma = AUTODMA, |
85 | .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, | 102 | .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, |
86 | .bootable = ON_BOARD, | 103 | .bootable = ON_BOARD, |
87 | },{ /* 1 */ | 104 | },{ /* 2 */ |
88 | .name = "SAMURAI", | 105 | .name = "SAMURAI", |
89 | .init_hwif = init_hwif_generic, | 106 | .init_hwif = init_hwif_generic, |
90 | .channels = 2, | 107 | .channels = 2, |
91 | .autodma = AUTODMA, | 108 | .autodma = AUTODMA, |
92 | .bootable = ON_BOARD, | 109 | .bootable = ON_BOARD, |
93 | },{ /* 2 */ | 110 | },{ /* 3 */ |
94 | .name = "HT6565", | 111 | .name = "HT6565", |
95 | .init_hwif = init_hwif_generic, | 112 | .init_hwif = init_hwif_generic, |
96 | .channels = 2, | 113 | .channels = 2, |
97 | .autodma = AUTODMA, | 114 | .autodma = AUTODMA, |
98 | .bootable = ON_BOARD, | 115 | .bootable = ON_BOARD, |
99 | },{ /* 3 */ | 116 | },{ /* 4 */ |
100 | .name = "UM8673F", | 117 | .name = "UM8673F", |
101 | .init_hwif = init_hwif_generic, | 118 | .init_hwif = init_hwif_generic, |
102 | .channels = 2, | 119 | .channels = 2, |
103 | .autodma = NODMA, | 120 | .autodma = NODMA, |
104 | .bootable = ON_BOARD, | 121 | .bootable = ON_BOARD, |
105 | },{ /* 4 */ | 122 | },{ /* 5 */ |
106 | .name = "UM8886A", | 123 | .name = "UM8886A", |
107 | .init_hwif = init_hwif_generic, | 124 | .init_hwif = init_hwif_generic, |
108 | .channels = 2, | 125 | .channels = 2, |
109 | .autodma = NODMA, | 126 | .autodma = NODMA, |
110 | .bootable = ON_BOARD, | 127 | .bootable = ON_BOARD, |
111 | },{ /* 5 */ | 128 | },{ /* 6 */ |
112 | .name = "UM8886BF", | 129 | .name = "UM8886BF", |
113 | .init_hwif = init_hwif_generic, | 130 | .init_hwif = init_hwif_generic, |
114 | .channels = 2, | 131 | .channels = 2, |
115 | .autodma = NODMA, | 132 | .autodma = NODMA, |
116 | .bootable = ON_BOARD, | 133 | .bootable = ON_BOARD, |
117 | },{ /* 6 */ | 134 | },{ /* 7 */ |
118 | .name = "HINT_IDE", | 135 | .name = "HINT_IDE", |
119 | .init_hwif = init_hwif_generic, | 136 | .init_hwif = init_hwif_generic, |
120 | .channels = 2, | 137 | .channels = 2, |
121 | .autodma = AUTODMA, | 138 | .autodma = AUTODMA, |
122 | .bootable = ON_BOARD, | 139 | .bootable = ON_BOARD, |
123 | },{ /* 7 */ | 140 | },{ /* 8 */ |
124 | .name = "VIA_IDE", | 141 | .name = "VIA_IDE", |
125 | .init_hwif = init_hwif_generic, | 142 | .init_hwif = init_hwif_generic, |
126 | .channels = 2, | 143 | .channels = 2, |
127 | .autodma = NOAUTODMA, | 144 | .autodma = NOAUTODMA, |
128 | .bootable = ON_BOARD, | 145 | .bootable = ON_BOARD, |
129 | },{ /* 8 */ | 146 | },{ /* 9 */ |
130 | .name = "OPTI621V", | 147 | .name = "OPTI621V", |
131 | .init_hwif = init_hwif_generic, | 148 | .init_hwif = init_hwif_generic, |
132 | .channels = 2, | 149 | .channels = 2, |
133 | .autodma = NOAUTODMA, | 150 | .autodma = NOAUTODMA, |
134 | .bootable = ON_BOARD, | 151 | .bootable = ON_BOARD, |
135 | },{ /* 9 */ | 152 | },{ /* 10 */ |
136 | .name = "VIA8237SATA", | 153 | .name = "VIA8237SATA", |
137 | .init_hwif = init_hwif_generic, | 154 | .init_hwif = init_hwif_generic, |
138 | .channels = 2, | 155 | .channels = 2, |
139 | .autodma = AUTODMA, | 156 | .autodma = AUTODMA, |
140 | .bootable = OFF_BOARD, | 157 | .bootable = OFF_BOARD, |
141 | },{ /* 10 */ | 158 | },{ /* 11 */ |
142 | .name = "Piccolo0102", | 159 | .name = "Piccolo0102", |
143 | .init_hwif = init_hwif_generic, | 160 | .init_hwif = init_hwif_generic, |
144 | .channels = 2, | 161 | .channels = 2, |
145 | .autodma = NOAUTODMA, | 162 | .autodma = NOAUTODMA, |
146 | .bootable = ON_BOARD, | 163 | .bootable = ON_BOARD, |
147 | },{ /* 11 */ | 164 | },{ /* 12 */ |
148 | .name = "Piccolo0103", | 165 | .name = "Piccolo0103", |
149 | .init_hwif = init_hwif_generic, | 166 | .init_hwif = init_hwif_generic, |
150 | .channels = 2, | 167 | .channels = 2, |
151 | .autodma = NOAUTODMA, | 168 | .autodma = NOAUTODMA, |
152 | .bootable = ON_BOARD, | 169 | .bootable = ON_BOARD, |
153 | },{ /* 12 */ | 170 | },{ /* 13 */ |
154 | .name = "Piccolo0105", | 171 | .name = "Piccolo0105", |
155 | .init_hwif = init_hwif_generic, | 172 | .init_hwif = init_hwif_generic, |
156 | .channels = 2, | 173 | .channels = 2, |
@@ -174,6 +191,10 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi | |||
174 | u16 command; | 191 | u16 command; |
175 | int ret = -ENODEV; | 192 | int ret = -ENODEV; |
176 | 193 | ||
194 | /* Don't use the generic entry unless instructed to do so */ | ||
195 | if (id->driver_data == 0 && ide_generic_all == 0) | ||
196 | goto out; | ||
197 | |||
177 | if (dev->vendor == PCI_VENDOR_ID_UMC && | 198 | if (dev->vendor == PCI_VENDOR_ID_UMC && |
178 | dev->device == PCI_DEVICE_ID_UMC_UM8886A && | 199 | dev->device == PCI_DEVICE_ID_UMC_UM8886A && |
179 | (!(PCI_FUNC(dev->devfn) & 1))) | 200 | (!(PCI_FUNC(dev->devfn) & 1))) |
@@ -195,21 +216,23 @@ out: | |||
195 | } | 216 | } |
196 | 217 | ||
197 | static struct pci_device_id generic_pci_tbl[] = { | 218 | static struct pci_device_id generic_pci_tbl[] = { |
198 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 219 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, |
199 | { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, | 220 | { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, |
200 | { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, | 221 | { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, |
201 | { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, | 222 | { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, |
202 | { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, | 223 | { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, |
203 | { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, | 224 | { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, |
204 | { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, | 225 | { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, |
205 | { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, | 226 | { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, |
206 | { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, | 227 | { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, |
207 | #ifdef CONFIG_BLK_DEV_IDE_SATA | 228 | #ifdef CONFIG_BLK_DEV_IDE_SATA |
208 | { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, | 229 | { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, |
209 | #endif | 230 | #endif |
210 | { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, | 231 | { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, |
211 | { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, | 232 | { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, |
212 | { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, | 233 | { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, |
234 | /* Must come last. If you add entries adjust this table appropriately and the init_one code */ | ||
235 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0}, | ||
213 | { 0, }, | 236 | { 0, }, |
214 | }; | 237 | }; |
215 | MODULE_DEVICE_TABLE(pci, generic_pci_tbl); | 238 | MODULE_DEVICE_TABLE(pci, generic_pci_tbl); |
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index c8ee0b8c0292..7b64db10d1b0 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c | |||
@@ -10,6 +10,11 @@ | |||
10 | * donation of an ABit BP6 mainboard, processor, and memory acellerated | 10 | * donation of an ABit BP6 mainboard, processor, and memory acellerated |
11 | * development and support. | 11 | * development and support. |
12 | * | 12 | * |
13 | * | ||
14 | * Highpoint have their own driver (source except for the raid part) | ||
15 | * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz | ||
16 | * This may be useful to anyone wanting to work on the mainstream hpt IDE. | ||
17 | * | ||
13 | * Note that final HPT370 support was done by force extraction of GPL. | 18 | * Note that final HPT370 support was done by force extraction of GPL. |
14 | * | 19 | * |
15 | * - add function for getting/setting power status of drive | 20 | * - add function for getting/setting power status of drive |
@@ -446,44 +451,29 @@ static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { | |||
446 | #define F_LOW_PCI_50 0x2d | 451 | #define F_LOW_PCI_50 0x2d |
447 | #define F_LOW_PCI_66 0x42 | 452 | #define F_LOW_PCI_66 0x42 |
448 | 453 | ||
449 | /* FIXME: compare with driver's code before removing */ | 454 | /* |
450 | #if 0 | 455 | * Hold all the highpoint quirks and revision information in one |
451 | if (hpt_minimum_revision(dev, 3)) { | 456 | * place. |
452 | u8 cbl; | 457 | */ |
453 | cbl = inb(iobase + 0x7b); | ||
454 | outb(cbl | 1, iobase + 0x7b); | ||
455 | outb(cbl & ~1, iobase + 0x7b); | ||
456 | cbl = inb(iobase + 0x7a); | ||
457 | p += sprintf(p, "Cable: ATA-%d" | ||
458 | " ATA-%d\n", | ||
459 | (cbl & 0x02) ? 33 : 66, | ||
460 | (cbl & 0x01) ? 33 : 66); | ||
461 | p += sprintf(p, "\n"); | ||
462 | } | ||
463 | { | ||
464 | u8 c2, c3; | ||
465 | /* older revs don't have these registers mapped | ||
466 | * into io space */ | ||
467 | pci_read_config_byte(dev, 0x43, &c0); | ||
468 | pci_read_config_byte(dev, 0x47, &c1); | ||
469 | pci_read_config_byte(dev, 0x4b, &c2); | ||
470 | pci_read_config_byte(dev, 0x4f, &c3); | ||
471 | |||
472 | p += sprintf(p, "Mode: %s %s" | ||
473 | " %s %s\n", | ||
474 | (c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : | ||
475 | (c0 & 0x80) ? "PIO " : "off ", | ||
476 | (c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " : | ||
477 | (c1 & 0x80) ? "PIO " : "off ", | ||
478 | (c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " : | ||
479 | (c2 & 0x80) ? "PIO " : "off ", | ||
480 | (c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " : | ||
481 | (c3 & 0x80) ? "PIO " : "off "); | ||
482 | } | ||
483 | } | ||
484 | #endif | ||
485 | 458 | ||
486 | static u32 hpt_revision (struct pci_dev *dev) | 459 | struct hpt_info |
460 | { | ||
461 | u8 max_mode; /* Speeds allowed */ | ||
462 | int revision; /* Chipset revision */ | ||
463 | int flags; /* Chipset properties */ | ||
464 | #define PLL_MODE 1 | ||
465 | #define IS_372N 2 | ||
466 | /* Speed table */ | ||
467 | struct chipset_bus_clock_list_entry *speed; | ||
468 | }; | ||
469 | |||
470 | /* | ||
471 | * This wants fixing so that we do everything not by classrev | ||
472 | * (which breaks on the newest chips) but by creating an | ||
473 | * enumeration of chip variants and using that | ||
474 | */ | ||
475 | |||
476 | static __devinit u32 hpt_revision (struct pci_dev *dev) | ||
487 | { | 477 | { |
488 | u32 class_rev; | 478 | u32 class_rev; |
489 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); | 479 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); |
@@ -507,37 +497,33 @@ static u32 hpt_revision (struct pci_dev *dev) | |||
507 | return class_rev; | 497 | return class_rev; |
508 | } | 498 | } |
509 | 499 | ||
510 | static u32 hpt_minimum_revision (struct pci_dev *dev, int revision) | ||
511 | { | ||
512 | unsigned int class_rev = hpt_revision(dev); | ||
513 | revision--; | ||
514 | return ((int) (class_rev > revision) ? 1 : 0); | ||
515 | } | ||
516 | |||
517 | static int check_in_drive_lists(ide_drive_t *drive, const char **list); | 500 | static int check_in_drive_lists(ide_drive_t *drive, const char **list); |
518 | 501 | ||
519 | static u8 hpt3xx_ratemask (ide_drive_t *drive) | 502 | static u8 hpt3xx_ratemask (ide_drive_t *drive) |
520 | { | 503 | { |
521 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 504 | ide_hwif_t *hwif = drive->hwif; |
505 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
522 | u8 mode = 0; | 506 | u8 mode = 0; |
523 | 507 | ||
524 | if (hpt_minimum_revision(dev, 8)) { /* HPT374 */ | 508 | /* FIXME: TODO - move this to set info->mode once at boot */ |
509 | |||
510 | if (info->revision >= 8) { /* HPT374 */ | ||
525 | mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; | 511 | mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; |
526 | } else if (hpt_minimum_revision(dev, 7)) { /* HPT371 */ | 512 | } else if (info->revision >= 7) { /* HPT371 */ |
527 | mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; | 513 | mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; |
528 | } else if (hpt_minimum_revision(dev, 6)) { /* HPT302 */ | 514 | } else if (info->revision >= 6) { /* HPT302 */ |
529 | mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; | 515 | mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; |
530 | } else if (hpt_minimum_revision(dev, 5)) { /* HPT372 */ | 516 | } else if (info->revision >= 5) { /* HPT372 */ |
531 | mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; | 517 | mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; |
532 | } else if (hpt_minimum_revision(dev, 4)) { /* HPT370A */ | 518 | } else if (info->revision >= 4) { /* HPT370A */ |
533 | mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; | 519 | mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; |
534 | } else if (hpt_minimum_revision(dev, 3)) { /* HPT370 */ | 520 | } else if (info->revision >= 3) { /* HPT370 */ |
535 | mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; | 521 | mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; |
536 | mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode; | 522 | mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode; |
537 | } else { /* HPT366 and HPT368 */ | 523 | } else { /* HPT366 and HPT368 */ |
538 | mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2; | 524 | mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2; |
539 | } | 525 | } |
540 | if (!eighty_ninty_three(drive) && (mode)) | 526 | if (!eighty_ninty_three(drive) && mode) |
541 | mode = min(mode, (u8)1); | 527 | mode = min(mode, (u8)1); |
542 | return mode; | 528 | return mode; |
543 | } | 529 | } |
@@ -549,7 +535,8 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive) | |||
549 | 535 | ||
550 | static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) | 536 | static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) |
551 | { | 537 | { |
552 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 538 | ide_hwif_t *hwif = drive->hwif; |
539 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
553 | u8 mode = hpt3xx_ratemask(drive); | 540 | u8 mode = hpt3xx_ratemask(drive); |
554 | 541 | ||
555 | if (drive->media != ide_disk) | 542 | if (drive->media != ide_disk) |
@@ -561,7 +548,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) | |||
561 | break; | 548 | break; |
562 | case 0x03: | 549 | case 0x03: |
563 | speed = min(speed, (u8)XFER_UDMA_5); | 550 | speed = min(speed, (u8)XFER_UDMA_5); |
564 | if (hpt_minimum_revision(dev, 5)) | 551 | if (info->revision >= 5) |
565 | break; | 552 | break; |
566 | if (check_in_drive_lists(drive, bad_ata100_5)) | 553 | if (check_in_drive_lists(drive, bad_ata100_5)) |
567 | speed = min(speed, (u8)XFER_UDMA_4); | 554 | speed = min(speed, (u8)XFER_UDMA_4); |
@@ -571,7 +558,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) | |||
571 | /* | 558 | /* |
572 | * CHECK ME, Does this need to be set to 5 ?? | 559 | * CHECK ME, Does this need to be set to 5 ?? |
573 | */ | 560 | */ |
574 | if (hpt_minimum_revision(dev, 3)) | 561 | if (info->revision >= 3) |
575 | break; | 562 | break; |
576 | if ((check_in_drive_lists(drive, bad_ata66_4)) || | 563 | if ((check_in_drive_lists(drive, bad_ata66_4)) || |
577 | (!(HPT366_ALLOW_ATA66_4))) | 564 | (!(HPT366_ALLOW_ATA66_4))) |
@@ -585,7 +572,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) | |||
585 | /* | 572 | /* |
586 | * CHECK ME, Does this need to be set to 5 ?? | 573 | * CHECK ME, Does this need to be set to 5 ?? |
587 | */ | 574 | */ |
588 | if (hpt_minimum_revision(dev, 3)) | 575 | if (info->revision >= 3) |
589 | break; | 576 | break; |
590 | if (check_in_drive_lists(drive, bad_ata33)) | 577 | if (check_in_drive_lists(drive, bad_ata33)) |
591 | speed = min(speed, (u8)XFER_MW_DMA_2); | 578 | speed = min(speed, (u8)XFER_MW_DMA_2); |
@@ -624,11 +611,12 @@ static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_ | |||
624 | 611 | ||
625 | static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) | 612 | static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) |
626 | { | 613 | { |
627 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 614 | ide_hwif_t *hwif = drive->hwif; |
615 | struct pci_dev *dev = hwif->pci_dev; | ||
616 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
628 | u8 speed = hpt3xx_ratefilter(drive, xferspeed); | 617 | u8 speed = hpt3xx_ratefilter(drive, xferspeed); |
629 | // u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); | ||
630 | u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; | 618 | u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; |
631 | u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; | 619 | u8 regfast = (hwif->channel) ? 0x55 : 0x51; |
632 | u8 drive_fast = 0; | 620 | u8 drive_fast = 0; |
633 | u32 reg1 = 0, reg2 = 0; | 621 | u32 reg1 = 0, reg2 = 0; |
634 | 622 | ||
@@ -636,16 +624,11 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) | |||
636 | * Disable the "fast interrupt" prediction. | 624 | * Disable the "fast interrupt" prediction. |
637 | */ | 625 | */ |
638 | pci_read_config_byte(dev, regfast, &drive_fast); | 626 | pci_read_config_byte(dev, regfast, &drive_fast); |
639 | #if 0 | ||
640 | if (drive_fast & 0x02) | ||
641 | pci_write_config_byte(dev, regfast, drive_fast & ~0x20); | ||
642 | #else | ||
643 | if (drive_fast & 0x80) | 627 | if (drive_fast & 0x80) |
644 | pci_write_config_byte(dev, regfast, drive_fast & ~0x80); | 628 | pci_write_config_byte(dev, regfast, drive_fast & ~0x80); |
645 | #endif | ||
646 | 629 | ||
647 | reg2 = pci_bus_clock_list(speed, | 630 | reg2 = pci_bus_clock_list(speed, info->speed); |
648 | (struct chipset_bus_clock_list_entry *) pci_get_drvdata(dev)); | 631 | |
649 | /* | 632 | /* |
650 | * Disable on-chip PIO FIFO/buffer | 633 | * Disable on-chip PIO FIFO/buffer |
651 | * (to avoid problems handling I/O errors later) | 634 | * (to avoid problems handling I/O errors later) |
@@ -665,10 +648,11 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) | |||
665 | 648 | ||
666 | static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) | 649 | static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) |
667 | { | 650 | { |
668 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 651 | ide_hwif_t *hwif = drive->hwif; |
652 | struct pci_dev *dev = hwif->pci_dev; | ||
653 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
669 | u8 speed = hpt3xx_ratefilter(drive, xferspeed); | 654 | u8 speed = hpt3xx_ratefilter(drive, xferspeed); |
670 | // u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); | 655 | u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; |
671 | u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; | ||
672 | u8 drive_pci = 0x40 + (drive->dn * 4); | 656 | u8 drive_pci = 0x40 + (drive->dn * 4); |
673 | u8 new_fast = 0, drive_fast = 0; | 657 | u8 new_fast = 0, drive_fast = 0; |
674 | u32 list_conf = 0, drive_conf = 0; | 658 | u32 list_conf = 0, drive_conf = 0; |
@@ -693,17 +677,13 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) | |||
693 | if (new_fast != drive_fast) | 677 | if (new_fast != drive_fast) |
694 | pci_write_config_byte(dev, regfast, new_fast); | 678 | pci_write_config_byte(dev, regfast, new_fast); |
695 | 679 | ||
696 | list_conf = pci_bus_clock_list(speed, | 680 | list_conf = pci_bus_clock_list(speed, info->speed); |
697 | (struct chipset_bus_clock_list_entry *) | ||
698 | pci_get_drvdata(dev)); | ||
699 | 681 | ||
700 | pci_read_config_dword(dev, drive_pci, &drive_conf); | 682 | pci_read_config_dword(dev, drive_pci, &drive_conf); |
701 | list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); | 683 | list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); |
702 | 684 | ||
703 | if (speed < XFER_MW_DMA_0) { | 685 | if (speed < XFER_MW_DMA_0) |
704 | list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ | 686 | list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ |
705 | } | ||
706 | |||
707 | pci_write_config_dword(dev, drive_pci, list_conf); | 687 | pci_write_config_dword(dev, drive_pci, list_conf); |
708 | 688 | ||
709 | return ide_config_drive_speed(drive, speed); | 689 | return ide_config_drive_speed(drive, speed); |
@@ -711,10 +691,11 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) | |||
711 | 691 | ||
712 | static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) | 692 | static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) |
713 | { | 693 | { |
714 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 694 | ide_hwif_t *hwif = drive->hwif; |
695 | struct pci_dev *dev = hwif->pci_dev; | ||
696 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
715 | u8 speed = hpt3xx_ratefilter(drive, xferspeed); | 697 | u8 speed = hpt3xx_ratefilter(drive, xferspeed); |
716 | // u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); | 698 | u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; |
717 | u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; | ||
718 | u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4); | 699 | u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4); |
719 | u32 list_conf = 0, drive_conf = 0; | 700 | u32 list_conf = 0, drive_conf = 0; |
720 | u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; | 701 | u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; |
@@ -726,10 +707,8 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) | |||
726 | pci_read_config_byte(dev, regfast, &drive_fast); | 707 | pci_read_config_byte(dev, regfast, &drive_fast); |
727 | drive_fast &= ~0x07; | 708 | drive_fast &= ~0x07; |
728 | pci_write_config_byte(dev, regfast, drive_fast); | 709 | pci_write_config_byte(dev, regfast, drive_fast); |
729 | 710 | ||
730 | list_conf = pci_bus_clock_list(speed, | 711 | list_conf = pci_bus_clock_list(speed, info->speed); |
731 | (struct chipset_bus_clock_list_entry *) | ||
732 | pci_get_drvdata(dev)); | ||
733 | pci_read_config_dword(dev, drive_pci, &drive_conf); | 712 | pci_read_config_dword(dev, drive_pci, &drive_conf); |
734 | list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); | 713 | list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); |
735 | if (speed < XFER_MW_DMA_0) | 714 | if (speed < XFER_MW_DMA_0) |
@@ -741,19 +720,14 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) | |||
741 | 720 | ||
742 | static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) | 721 | static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) |
743 | { | 722 | { |
744 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 723 | ide_hwif_t *hwif = drive->hwif; |
724 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
745 | 725 | ||
746 | if (hpt_minimum_revision(dev, 8)) | 726 | if (info->revision >= 8) |
747 | return hpt372_tune_chipset(drive, speed); /* not a typo */ | 727 | return hpt372_tune_chipset(drive, speed); /* not a typo */ |
748 | #if 0 | 728 | else if (info->revision >= 5) |
749 | else if (hpt_minimum_revision(dev, 7)) | ||
750 | hpt371_tune_chipset(drive, speed); | ||
751 | else if (hpt_minimum_revision(dev, 6)) | ||
752 | hpt302_tune_chipset(drive, speed); | ||
753 | #endif | ||
754 | else if (hpt_minimum_revision(dev, 5)) | ||
755 | return hpt372_tune_chipset(drive, speed); | 729 | return hpt372_tune_chipset(drive, speed); |
756 | else if (hpt_minimum_revision(dev, 3)) | 730 | else if (info->revision >= 3) |
757 | return hpt370_tune_chipset(drive, speed); | 731 | return hpt370_tune_chipset(drive, speed); |
758 | else /* hpt368: hpt_minimum_revision(dev, 2) */ | 732 | else /* hpt368: hpt_minimum_revision(dev, 2) */ |
759 | return hpt36x_tune_chipset(drive, speed); | 733 | return hpt36x_tune_chipset(drive, speed); |
@@ -779,8 +753,14 @@ static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) | |||
779 | static int config_chipset_for_dma (ide_drive_t *drive) | 753 | static int config_chipset_for_dma (ide_drive_t *drive) |
780 | { | 754 | { |
781 | u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); | 755 | u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); |
756 | ide_hwif_t *hwif = drive->hwif; | ||
757 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
782 | 758 | ||
783 | if (!(speed)) | 759 | if (!speed) |
760 | return 0; | ||
761 | |||
762 | /* If we don't have any timings we can't do a lot */ | ||
763 | if (info->speed == NULL) | ||
784 | return 0; | 764 | return 0; |
785 | 765 | ||
786 | (void) hpt3xx_tune_chipset(drive, speed); | 766 | (void) hpt3xx_tune_chipset(drive, speed); |
@@ -794,7 +774,7 @@ static int hpt3xx_quirkproc (ide_drive_t *drive) | |||
794 | 774 | ||
795 | static void hpt3xx_intrproc (ide_drive_t *drive) | 775 | static void hpt3xx_intrproc (ide_drive_t *drive) |
796 | { | 776 | { |
797 | ide_hwif_t *hwif = HWIF(drive); | 777 | ide_hwif_t *hwif = drive->hwif; |
798 | 778 | ||
799 | if (drive->quirk_list) | 779 | if (drive->quirk_list) |
800 | return; | 780 | return; |
@@ -804,24 +784,26 @@ static void hpt3xx_intrproc (ide_drive_t *drive) | |||
804 | 784 | ||
805 | static void hpt3xx_maskproc (ide_drive_t *drive, int mask) | 785 | static void hpt3xx_maskproc (ide_drive_t *drive, int mask) |
806 | { | 786 | { |
807 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 787 | ide_hwif_t *hwif = drive->hwif; |
788 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
789 | struct pci_dev *dev = hwif->pci_dev; | ||
808 | 790 | ||
809 | if (drive->quirk_list) { | 791 | if (drive->quirk_list) { |
810 | if (hpt_minimum_revision(dev,3)) { | 792 | if (info->revision >= 3) { |
811 | u8 reg5a = 0; | 793 | u8 reg5a = 0; |
812 | pci_read_config_byte(dev, 0x5a, ®5a); | 794 | pci_read_config_byte(dev, 0x5a, ®5a); |
813 | if (((reg5a & 0x10) >> 4) != mask) | 795 | if (((reg5a & 0x10) >> 4) != mask) |
814 | pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); | 796 | pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); |
815 | } else { | 797 | } else { |
816 | if (mask) { | 798 | if (mask) { |
817 | disable_irq(HWIF(drive)->irq); | 799 | disable_irq(hwif->irq); |
818 | } else { | 800 | } else { |
819 | enable_irq(HWIF(drive)->irq); | 801 | enable_irq(hwif->irq); |
820 | } | 802 | } |
821 | } | 803 | } |
822 | } else { | 804 | } else { |
823 | if (IDE_CONTROL_REG) | 805 | if (IDE_CONTROL_REG) |
824 | HWIF(drive)->OUTB(mask ? (drive->ctl | 2) : | 806 | hwif->OUTB(mask ? (drive->ctl | 2) : |
825 | (drive->ctl & ~2), | 807 | (drive->ctl & ~2), |
826 | IDE_CONTROL_REG); | 808 | IDE_CONTROL_REG); |
827 | } | 809 | } |
@@ -829,12 +811,12 @@ static void hpt3xx_maskproc (ide_drive_t *drive, int mask) | |||
829 | 811 | ||
830 | static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) | 812 | static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) |
831 | { | 813 | { |
832 | ide_hwif_t *hwif = HWIF(drive); | 814 | ide_hwif_t *hwif = drive->hwif; |
833 | struct hd_driveid *id = drive->id; | 815 | struct hd_driveid *id = drive->id; |
834 | 816 | ||
835 | drive->init_speed = 0; | 817 | drive->init_speed = 0; |
836 | 818 | ||
837 | if (id && (id->capability & 1) && drive->autodma) { | 819 | if ((id->capability & 1) && drive->autodma) { |
838 | 820 | ||
839 | if (ide_use_dma(drive)) { | 821 | if (ide_use_dma(drive)) { |
840 | if (config_chipset_for_dma(drive)) | 822 | if (config_chipset_for_dma(drive)) |
@@ -868,15 +850,6 @@ static int hpt366_ide_dma_lostirq (ide_drive_t *drive) | |||
868 | drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); | 850 | drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); |
869 | if (reg5ah & 0x10) | 851 | if (reg5ah & 0x10) |
870 | pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); | 852 | pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); |
871 | #if 0 | ||
872 | /* how about we flush and reset, mmmkay? */ | ||
873 | pci_write_config_byte(dev, 0x51, 0x1F); | ||
874 | /* fall through to a reset */ | ||
875 | case dma_start: | ||
876 | case ide_dma_end: | ||
877 | /* reset the chips state over and over.. */ | ||
878 | pci_write_config_byte(dev, 0x51, 0x13); | ||
879 | #endif | ||
880 | return __ide_dma_lostirq(drive); | 853 | return __ide_dma_lostirq(drive); |
881 | } | 854 | } |
882 | 855 | ||
@@ -919,7 +892,7 @@ static void hpt370_lostirq_timeout (ide_drive_t *drive) | |||
919 | u8 dma_stat = 0, dma_cmd = 0; | 892 | u8 dma_stat = 0, dma_cmd = 0; |
920 | 893 | ||
921 | pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); | 894 | pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); |
922 | printk("%s: %d bytes in FIFO\n", drive->name, bfifo); | 895 | printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo); |
923 | hpt370_clear_engine(drive); | 896 | hpt370_clear_engine(drive); |
924 | /* get dma command mode */ | 897 | /* get dma command mode */ |
925 | dma_cmd = hwif->INB(hwif->dma_command); | 898 | dma_cmd = hwif->INB(hwif->dma_command); |
@@ -1047,15 +1020,6 @@ static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq) | |||
1047 | 1020 | ||
1048 | static void hpt3xx_reset (ide_drive_t *drive) | 1021 | static void hpt3xx_reset (ide_drive_t *drive) |
1049 | { | 1022 | { |
1050 | #if 0 | ||
1051 | unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); | ||
1052 | u8 reset = (HWIF(drive)->channel) ? 0x80 : 0x40; | ||
1053 | u8 reg59h = 0; | ||
1054 | |||
1055 | pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, ®59h); | ||
1056 | pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset); | ||
1057 | pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h); | ||
1058 | #endif | ||
1059 | } | 1023 | } |
1060 | 1024 | ||
1061 | static int hpt3xx_tristate (ide_drive_t * drive, int state) | 1025 | static int hpt3xx_tristate (ide_drive_t * drive, int state) |
@@ -1065,8 +1029,6 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state) | |||
1065 | u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; | 1029 | u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; |
1066 | u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; | 1030 | u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; |
1067 | 1031 | ||
1068 | // hwif->bus_state = state; | ||
1069 | |||
1070 | pci_read_config_byte(dev, 0x59, ®59h); | 1032 | pci_read_config_byte(dev, 0x59, ®59h); |
1071 | pci_read_config_byte(dev, state_reg, ®XXh); | 1033 | pci_read_config_byte(dev, state_reg, ®XXh); |
1072 | 1034 | ||
@@ -1093,7 +1055,7 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state) | |||
1093 | #define TRISTATE_BIT 0x8000 | 1055 | #define TRISTATE_BIT 0x8000 |
1094 | static int hpt370_busproc(ide_drive_t * drive, int state) | 1056 | static int hpt370_busproc(ide_drive_t * drive, int state) |
1095 | { | 1057 | { |
1096 | ide_hwif_t *hwif = HWIF(drive); | 1058 | ide_hwif_t *hwif = drive->hwif; |
1097 | struct pci_dev *dev = hwif->pci_dev; | 1059 | struct pci_dev *dev = hwif->pci_dev; |
1098 | u8 tristate = 0, resetmask = 0, bus_reg = 0; | 1060 | u8 tristate = 0, resetmask = 0, bus_reg = 0; |
1099 | u16 tri_reg; | 1061 | u16 tri_reg; |
@@ -1148,33 +1110,44 @@ static int hpt370_busproc(ide_drive_t * drive, int state) | |||
1148 | return 0; | 1110 | return 0; |
1149 | } | 1111 | } |
1150 | 1112 | ||
1151 | static int __devinit init_hpt37x(struct pci_dev *dev) | 1113 | static void __devinit hpt366_clocking(ide_hwif_t *hwif) |
1152 | { | 1114 | { |
1115 | u32 reg1 = 0; | ||
1116 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
1117 | |||
1118 | pci_read_config_dword(hwif->pci_dev, 0x40, ®1); | ||
1119 | |||
1120 | /* detect bus speed by looking at control reg timing: */ | ||
1121 | switch((reg1 >> 8) & 7) { | ||
1122 | case 5: | ||
1123 | info->speed = forty_base_hpt366; | ||
1124 | break; | ||
1125 | case 9: | ||
1126 | info->speed = twenty_five_base_hpt366; | ||
1127 | break; | ||
1128 | case 7: | ||
1129 | default: | ||
1130 | info->speed = thirty_three_base_hpt366; | ||
1131 | break; | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | static void __devinit hpt37x_clocking(ide_hwif_t *hwif) | ||
1136 | { | ||
1137 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
1138 | struct pci_dev *dev = hwif->pci_dev; | ||
1153 | int adjust, i; | 1139 | int adjust, i; |
1154 | u16 freq; | 1140 | u16 freq; |
1155 | u32 pll; | 1141 | u32 pll; |
1156 | u8 reg5bh; | 1142 | u8 reg5bh; |
1157 | u8 reg5ah = 0; | ||
1158 | unsigned long dmabase = pci_resource_start(dev, 4); | ||
1159 | u8 did, rid; | ||
1160 | int is_372n = 0; | ||
1161 | 1143 | ||
1162 | pci_read_config_byte(dev, 0x5a, ®5ah); | ||
1163 | /* interrupt force enable */ | ||
1164 | pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); | ||
1165 | |||
1166 | if(dmabase) | ||
1167 | { | ||
1168 | did = inb(dmabase + 0x22); | ||
1169 | rid = inb(dmabase + 0x28); | ||
1170 | |||
1171 | if((did == 4 && rid == 6) || (did == 5 && rid > 1)) | ||
1172 | is_372n = 1; | ||
1173 | } | ||
1174 | |||
1175 | /* | 1144 | /* |
1176 | * default to pci clock. make sure MA15/16 are set to output | 1145 | * default to pci clock. make sure MA15/16 are set to output |
1177 | * to prevent drives having problems with 40-pin cables. | 1146 | * to prevent drives having problems with 40-pin cables. Needed |
1147 | * for some drives such as IBM-DTLA which will not enter ready | ||
1148 | * state on reset when PDIAG is a input. | ||
1149 | * | ||
1150 | * ToDo: should we set 0x21 when using PLL mode ? | ||
1178 | */ | 1151 | */ |
1179 | pci_write_config_byte(dev, 0x5b, 0x23); | 1152 | pci_write_config_byte(dev, 0x5b, 0x23); |
1180 | 1153 | ||
@@ -1197,9 +1170,7 @@ static int __devinit init_hpt37x(struct pci_dev *dev) | |||
1197 | * Currently we always set up the PLL for the 372N | 1170 | * Currently we always set up the PLL for the 372N |
1198 | */ | 1171 | */ |
1199 | 1172 | ||
1200 | pci_set_drvdata(dev, NULL); | 1173 | if(info->flags & IS_372N) |
1201 | |||
1202 | if(is_372n) | ||
1203 | { | 1174 | { |
1204 | printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n"); | 1175 | printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n"); |
1205 | if(freq < 0x55) | 1176 | if(freq < 0x55) |
@@ -1227,39 +1198,38 @@ static int __devinit init_hpt37x(struct pci_dev *dev) | |||
1227 | pll = F_LOW_PCI_66; | 1198 | pll = F_LOW_PCI_66; |
1228 | 1199 | ||
1229 | if (pll == F_LOW_PCI_33) { | 1200 | if (pll == F_LOW_PCI_33) { |
1230 | if (hpt_minimum_revision(dev,8)) | 1201 | if (info->revision >= 8) |
1231 | pci_set_drvdata(dev, (void *) thirty_three_base_hpt374); | 1202 | info->speed = thirty_three_base_hpt374; |
1232 | else if (hpt_minimum_revision(dev,5)) | 1203 | else if (info->revision >= 5) |
1233 | pci_set_drvdata(dev, (void *) thirty_three_base_hpt372); | 1204 | info->speed = thirty_three_base_hpt372; |
1234 | else if (hpt_minimum_revision(dev,4)) | 1205 | else if (info->revision >= 4) |
1235 | pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a); | 1206 | info->speed = thirty_three_base_hpt370a; |
1236 | else | 1207 | else |
1237 | pci_set_drvdata(dev, (void *) thirty_three_base_hpt370); | 1208 | info->speed = thirty_three_base_hpt370; |
1238 | printk("HPT37X: using 33MHz PCI clock\n"); | 1209 | printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); |
1239 | } else if (pll == F_LOW_PCI_40) { | 1210 | } else if (pll == F_LOW_PCI_40) { |
1240 | /* Unsupported */ | 1211 | /* Unsupported */ |
1241 | } else if (pll == F_LOW_PCI_50) { | 1212 | } else if (pll == F_LOW_PCI_50) { |
1242 | if (hpt_minimum_revision(dev,8)) | 1213 | if (info->revision >= 8) |
1243 | pci_set_drvdata(dev, (void *) fifty_base_hpt370a); | 1214 | info->speed = fifty_base_hpt370a; |
1244 | else if (hpt_minimum_revision(dev,5)) | 1215 | else if (info->revision >= 5) |
1245 | pci_set_drvdata(dev, (void *) fifty_base_hpt372); | 1216 | info->speed = fifty_base_hpt372; |
1246 | else if (hpt_minimum_revision(dev,4)) | 1217 | else if (info->revision >= 4) |
1247 | pci_set_drvdata(dev, (void *) fifty_base_hpt370a); | 1218 | info->speed = fifty_base_hpt370a; |
1248 | else | 1219 | else |
1249 | pci_set_drvdata(dev, (void *) fifty_base_hpt370a); | 1220 | info->speed = fifty_base_hpt370a; |
1250 | printk("HPT37X: using 50MHz PCI clock\n"); | 1221 | printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); |
1251 | } else { | 1222 | } else { |
1252 | if (hpt_minimum_revision(dev,8)) | 1223 | if (info->revision >= 8) { |
1253 | { | ||
1254 | printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n"); | 1224 | printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n"); |
1255 | } | 1225 | } |
1256 | else if (hpt_minimum_revision(dev,5)) | 1226 | else if (info->revision >= 5) |
1257 | pci_set_drvdata(dev, (void *) sixty_six_base_hpt372); | 1227 | info->speed = sixty_six_base_hpt372; |
1258 | else if (hpt_minimum_revision(dev,4)) | 1228 | else if (info->revision >= 4) |
1259 | pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a); | 1229 | info->speed = sixty_six_base_hpt370a; |
1260 | else | 1230 | else |
1261 | pci_set_drvdata(dev, (void *) sixty_six_base_hpt370); | 1231 | info->speed = sixty_six_base_hpt370; |
1262 | printk("HPT37X: using 66MHz PCI clock\n"); | 1232 | printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); |
1263 | } | 1233 | } |
1264 | } | 1234 | } |
1265 | 1235 | ||
@@ -1269,11 +1239,19 @@ static int __devinit init_hpt37x(struct pci_dev *dev) | |||
1269 | * result in slow reads when using a 33MHz PCI clock. we also | 1239 | * result in slow reads when using a 33MHz PCI clock. we also |
1270 | * don't like to use the PLL because it will cause glitches | 1240 | * don't like to use the PLL because it will cause glitches |
1271 | * on PRST/SRST when the HPT state engine gets reset. | 1241 | * on PRST/SRST when the HPT state engine gets reset. |
1242 | * | ||
1243 | * ToDo: Use 66MHz PLL when ATA133 devices are present on a | ||
1244 | * 372 device so we can get ATA133 support | ||
1272 | */ | 1245 | */ |
1273 | if (pci_get_drvdata(dev)) | 1246 | if (info->speed) |
1274 | goto init_hpt37X_done; | 1247 | goto init_hpt37X_done; |
1248 | |||
1249 | info->flags |= PLL_MODE; | ||
1275 | 1250 | ||
1276 | /* | 1251 | /* |
1252 | * FIXME: make this work correctly, esp with 372N as per | ||
1253 | * reference driver code. | ||
1254 | * | ||
1277 | * adjust PLL based upon PCI clock, enable it, and wait for | 1255 | * adjust PLL based upon PCI clock, enable it, and wait for |
1278 | * stabilization. | 1256 | * stabilization. |
1279 | */ | 1257 | */ |
@@ -1298,14 +1276,14 @@ static int __devinit init_hpt37x(struct pci_dev *dev) | |||
1298 | pci_write_config_dword(dev, 0x5c, | 1276 | pci_write_config_dword(dev, 0x5c, |
1299 | pll & ~0x100); | 1277 | pll & ~0x100); |
1300 | pci_write_config_byte(dev, 0x5b, 0x21); | 1278 | pci_write_config_byte(dev, 0x5b, 0x21); |
1301 | if (hpt_minimum_revision(dev,8)) | 1279 | if (info->revision >= 8) |
1302 | pci_set_drvdata(dev, (void *) fifty_base_hpt370a); | 1280 | info->speed = fifty_base_hpt370a; |
1303 | else if (hpt_minimum_revision(dev,5)) | 1281 | else if (info->revision >= 5) |
1304 | pci_set_drvdata(dev, (void *) fifty_base_hpt372); | 1282 | info->speed = fifty_base_hpt372; |
1305 | else if (hpt_minimum_revision(dev,4)) | 1283 | else if (info->revision >= 4) |
1306 | pci_set_drvdata(dev, (void *) fifty_base_hpt370a); | 1284 | info->speed = fifty_base_hpt370a; |
1307 | else | 1285 | else |
1308 | pci_set_drvdata(dev, (void *) fifty_base_hpt370a); | 1286 | info->speed = fifty_base_hpt370a; |
1309 | printk("HPT37X: using 50MHz internal PLL\n"); | 1287 | printk("HPT37X: using 50MHz internal PLL\n"); |
1310 | goto init_hpt37X_done; | 1288 | goto init_hpt37X_done; |
1311 | } | 1289 | } |
@@ -1318,10 +1296,22 @@ pll_recal: | |||
1318 | } | 1296 | } |
1319 | 1297 | ||
1320 | init_hpt37X_done: | 1298 | init_hpt37X_done: |
1299 | if (!info->speed) | ||
1300 | printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n", | ||
1301 | (info->flags & IS_372N)?"N":"", pll, freq); | ||
1321 | /* reset state engine */ | 1302 | /* reset state engine */ |
1322 | pci_write_config_byte(dev, 0x50, 0x37); | 1303 | pci_write_config_byte(dev, 0x50, 0x37); |
1323 | pci_write_config_byte(dev, 0x54, 0x37); | 1304 | pci_write_config_byte(dev, 0x54, 0x37); |
1324 | udelay(100); | 1305 | udelay(100); |
1306 | } | ||
1307 | |||
1308 | static int __devinit init_hpt37x(struct pci_dev *dev) | ||
1309 | { | ||
1310 | u8 reg5ah; | ||
1311 | |||
1312 | pci_read_config_byte(dev, 0x5a, ®5ah); | ||
1313 | /* interrupt force enable */ | ||
1314 | pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); | ||
1325 | return 0; | 1315 | return 0; |
1326 | } | 1316 | } |
1327 | 1317 | ||
@@ -1338,59 +1328,27 @@ static int __devinit init_hpt366(struct pci_dev *dev) | |||
1338 | pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); | 1328 | pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); |
1339 | pci_read_config_dword(dev, 0x40, ®1); | 1329 | pci_read_config_dword(dev, 0x40, ®1); |
1340 | 1330 | ||
1341 | /* detect bus speed by looking at control reg timing: */ | ||
1342 | switch((reg1 >> 8) & 7) { | ||
1343 | case 5: | ||
1344 | pci_set_drvdata(dev, (void *) forty_base_hpt366); | ||
1345 | break; | ||
1346 | case 9: | ||
1347 | pci_set_drvdata(dev, (void *) twenty_five_base_hpt366); | ||
1348 | break; | ||
1349 | case 7: | ||
1350 | default: | ||
1351 | pci_set_drvdata(dev, (void *) thirty_three_base_hpt366); | ||
1352 | break; | ||
1353 | } | ||
1354 | |||
1355 | if (!pci_get_drvdata(dev)) | ||
1356 | { | ||
1357 | printk(KERN_ERR "hpt366: unknown bus timing.\n"); | ||
1358 | pci_set_drvdata(dev, NULL); | ||
1359 | } | ||
1360 | return 0; | 1331 | return 0; |
1361 | } | 1332 | } |
1362 | 1333 | ||
1363 | static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) | 1334 | static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) |
1364 | { | 1335 | { |
1365 | int ret = 0; | 1336 | int ret = 0; |
1366 | u8 test = 0; | 1337 | /* FIXME: Not portable */ |
1367 | |||
1368 | if (dev->resource[PCI_ROM_RESOURCE].start) | 1338 | if (dev->resource[PCI_ROM_RESOURCE].start) |
1369 | pci_write_config_byte(dev, PCI_ROM_ADDRESS, | 1339 | pci_write_config_byte(dev, PCI_ROM_ADDRESS, |
1370 | dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); | 1340 | dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); |
1371 | 1341 | ||
1372 | pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); | 1342 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); |
1373 | if (test != (L1_CACHE_BYTES / 4)) | 1343 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); |
1374 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, | 1344 | pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); |
1375 | (L1_CACHE_BYTES / 4)); | 1345 | pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); |
1376 | |||
1377 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); | ||
1378 | if (test != 0x78) | ||
1379 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); | ||
1380 | 1346 | ||
1381 | pci_read_config_byte(dev, PCI_MIN_GNT, &test); | 1347 | if (hpt_revision(dev) >= 3) |
1382 | if (test != 0x08) | ||
1383 | pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); | ||
1384 | |||
1385 | pci_read_config_byte(dev, PCI_MAX_LAT, &test); | ||
1386 | if (test != 0x08) | ||
1387 | pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); | ||
1388 | |||
1389 | if (hpt_minimum_revision(dev, 3)) { | ||
1390 | ret = init_hpt37x(dev); | 1348 | ret = init_hpt37x(dev); |
1391 | } else { | 1349 | else |
1392 | ret =init_hpt366(dev); | 1350 | ret = init_hpt366(dev); |
1393 | } | 1351 | |
1394 | if (ret) | 1352 | if (ret) |
1395 | return ret; | 1353 | return ret; |
1396 | 1354 | ||
@@ -1400,27 +1358,16 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
1400 | static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | 1358 | static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) |
1401 | { | 1359 | { |
1402 | struct pci_dev *dev = hwif->pci_dev; | 1360 | struct pci_dev *dev = hwif->pci_dev; |
1361 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
1403 | u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; | 1362 | u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; |
1404 | u8 did, rid; | ||
1405 | unsigned long dmabase = hwif->dma_base; | ||
1406 | int is_372n = 0; | ||
1407 | 1363 | ||
1408 | if(dmabase) | ||
1409 | { | ||
1410 | did = inb(dmabase + 0x22); | ||
1411 | rid = inb(dmabase + 0x28); | ||
1412 | |||
1413 | if((did == 4 && rid == 6) || (did == 5 && rid > 1)) | ||
1414 | is_372n = 1; | ||
1415 | } | ||
1416 | |||
1417 | hwif->tuneproc = &hpt3xx_tune_drive; | 1364 | hwif->tuneproc = &hpt3xx_tune_drive; |
1418 | hwif->speedproc = &hpt3xx_tune_chipset; | 1365 | hwif->speedproc = &hpt3xx_tune_chipset; |
1419 | hwif->quirkproc = &hpt3xx_quirkproc; | 1366 | hwif->quirkproc = &hpt3xx_quirkproc; |
1420 | hwif->intrproc = &hpt3xx_intrproc; | 1367 | hwif->intrproc = &hpt3xx_intrproc; |
1421 | hwif->maskproc = &hpt3xx_maskproc; | 1368 | hwif->maskproc = &hpt3xx_maskproc; |
1422 | 1369 | ||
1423 | if(is_372n) | 1370 | if(info->flags & IS_372N) |
1424 | hwif->rw_disk = &hpt372n_rw_disk; | 1371 | hwif->rw_disk = &hpt372n_rw_disk; |
1425 | 1372 | ||
1426 | /* | 1373 | /* |
@@ -1428,7 +1375,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | |||
1428 | * address lines to access an external eeprom. To read valid | 1375 | * address lines to access an external eeprom. To read valid |
1429 | * cable detect state the pins must be enabled as inputs. | 1376 | * cable detect state the pins must be enabled as inputs. |
1430 | */ | 1377 | */ |
1431 | if (hpt_minimum_revision(dev, 8) && PCI_FUNC(dev->devfn) & 1) { | 1378 | if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) { |
1432 | /* | 1379 | /* |
1433 | * HPT374 PCI function 1 | 1380 | * HPT374 PCI function 1 |
1434 | * - set bit 15 of reg 0x52 to enable TCBLID as input | 1381 | * - set bit 15 of reg 0x52 to enable TCBLID as input |
@@ -1443,7 +1390,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | |||
1443 | pci_read_config_byte(dev, 0x5a, &ata66); | 1390 | pci_read_config_byte(dev, 0x5a, &ata66); |
1444 | pci_write_config_word(dev, 0x52, mcr3); | 1391 | pci_write_config_word(dev, 0x52, mcr3); |
1445 | pci_write_config_word(dev, 0x56, mcr6); | 1392 | pci_write_config_word(dev, 0x56, mcr6); |
1446 | } else if (hpt_minimum_revision(dev, 3)) { | 1393 | } else if (info->revision >= 3) { |
1447 | /* | 1394 | /* |
1448 | * HPT370/372 and 374 pcifn 0 | 1395 | * HPT370/372 and 374 pcifn 0 |
1449 | * - clear bit 0 of 0x5b to enable P/SCBLID as inputs | 1396 | * - clear bit 0 of 0x5b to enable P/SCBLID as inputs |
@@ -1470,7 +1417,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | |||
1470 | hwif->serialized = hwif->mate->serialized = 1; | 1417 | hwif->serialized = hwif->mate->serialized = 1; |
1471 | #endif | 1418 | #endif |
1472 | 1419 | ||
1473 | if (hpt_minimum_revision(dev,3)) { | 1420 | if (info->revision >= 3) { |
1474 | u8 reg5ah = 0; | 1421 | u8 reg5ah = 0; |
1475 | pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); | 1422 | pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); |
1476 | /* | 1423 | /* |
@@ -1480,8 +1427,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | |||
1480 | */ | 1427 | */ |
1481 | hwif->resetproc = &hpt3xx_reset; | 1428 | hwif->resetproc = &hpt3xx_reset; |
1482 | hwif->busproc = &hpt370_busproc; | 1429 | hwif->busproc = &hpt370_busproc; |
1483 | // hwif->drives[0].autotune = hwif->drives[1].autotune = 1; | 1430 | } else if (info->revision >= 2) { |
1484 | } else if (hpt_minimum_revision(dev,2)) { | ||
1485 | hwif->resetproc = &hpt3xx_reset; | 1431 | hwif->resetproc = &hpt3xx_reset; |
1486 | hwif->busproc = &hpt3xx_tristate; | 1432 | hwif->busproc = &hpt3xx_tristate; |
1487 | } else { | 1433 | } else { |
@@ -1502,18 +1448,18 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | |||
1502 | hwif->udma_four = ((ata66 & regmask) ? 0 : 1); | 1448 | hwif->udma_four = ((ata66 & regmask) ? 0 : 1); |
1503 | hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; | 1449 | hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; |
1504 | 1450 | ||
1505 | if (hpt_minimum_revision(dev,8)) { | 1451 | if (info->revision >= 8) { |
1506 | hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; | 1452 | hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; |
1507 | hwif->ide_dma_end = &hpt374_ide_dma_end; | 1453 | hwif->ide_dma_end = &hpt374_ide_dma_end; |
1508 | } else if (hpt_minimum_revision(dev,5)) { | 1454 | } else if (info->revision >= 5) { |
1509 | hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; | 1455 | hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; |
1510 | hwif->ide_dma_end = &hpt374_ide_dma_end; | 1456 | hwif->ide_dma_end = &hpt374_ide_dma_end; |
1511 | } else if (hpt_minimum_revision(dev,3)) { | 1457 | } else if (info->revision >= 3) { |
1512 | hwif->dma_start = &hpt370_ide_dma_start; | 1458 | hwif->dma_start = &hpt370_ide_dma_start; |
1513 | hwif->ide_dma_end = &hpt370_ide_dma_end; | 1459 | hwif->ide_dma_end = &hpt370_ide_dma_end; |
1514 | hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; | 1460 | hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; |
1515 | hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; | 1461 | hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; |
1516 | } else if (hpt_minimum_revision(dev,2)) | 1462 | } else if (info->revision >= 2) |
1517 | hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; | 1463 | hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; |
1518 | else | 1464 | else |
1519 | hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; | 1465 | hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; |
@@ -1526,6 +1472,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | |||
1526 | 1472 | ||
1527 | static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) | 1473 | static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) |
1528 | { | 1474 | { |
1475 | struct hpt_info *info = ide_get_hwifdata(hwif); | ||
1529 | u8 masterdma = 0, slavedma = 0; | 1476 | u8 masterdma = 0, slavedma = 0; |
1530 | u8 dma_new = 0, dma_old = 0; | 1477 | u8 dma_new = 0, dma_old = 0; |
1531 | u8 primary = hwif->channel ? 0x4b : 0x43; | 1478 | u8 primary = hwif->channel ? 0x4b : 0x43; |
@@ -1535,8 +1482,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) | |||
1535 | if (!dmabase) | 1482 | if (!dmabase) |
1536 | return; | 1483 | return; |
1537 | 1484 | ||
1538 | if(pci_get_drvdata(hwif->pci_dev) == NULL) | 1485 | if(info->speed == NULL) { |
1539 | { | ||
1540 | printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n"); | 1486 | printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n"); |
1541 | return; | 1487 | return; |
1542 | } | 1488 | } |
@@ -1559,6 +1505,40 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) | |||
1559 | ide_setup_dma(hwif, dmabase, 8); | 1505 | ide_setup_dma(hwif, dmabase, 8); |
1560 | } | 1506 | } |
1561 | 1507 | ||
1508 | /* | ||
1509 | * We "borrow" this hook in order to set the data structures | ||
1510 | * up early enough before dma or init_hwif calls are made. | ||
1511 | */ | ||
1512 | |||
1513 | static void __devinit init_iops_hpt366(ide_hwif_t *hwif) | ||
1514 | { | ||
1515 | struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); | ||
1516 | unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4); | ||
1517 | u8 did, rid; | ||
1518 | |||
1519 | if(info == NULL) { | ||
1520 | printk(KERN_WARNING "hpt366: out of memory.\n"); | ||
1521 | return; | ||
1522 | } | ||
1523 | memset(info, 0, sizeof(struct hpt_info)); | ||
1524 | ide_set_hwifdata(hwif, info); | ||
1525 | |||
1526 | if(dmabase) { | ||
1527 | did = inb(dmabase + 0x22); | ||
1528 | rid = inb(dmabase + 0x28); | ||
1529 | |||
1530 | if((did == 4 && rid == 6) || (did == 5 && rid > 1)) | ||
1531 | info->flags |= IS_372N; | ||
1532 | } | ||
1533 | |||
1534 | info->revision = hpt_revision(hwif->pci_dev); | ||
1535 | |||
1536 | if (info->revision >= 3) | ||
1537 | hpt37x_clocking(hwif); | ||
1538 | else | ||
1539 | hpt366_clocking(hwif); | ||
1540 | } | ||
1541 | |||
1562 | static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) | 1542 | static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) |
1563 | { | 1543 | { |
1564 | struct pci_dev *findev = NULL; | 1544 | struct pci_dev *findev = NULL; |
@@ -1646,6 +1626,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { | |||
1646 | .name = "HPT366", | 1626 | .name = "HPT366", |
1647 | .init_setup = init_setup_hpt366, | 1627 | .init_setup = init_setup_hpt366, |
1648 | .init_chipset = init_chipset_hpt366, | 1628 | .init_chipset = init_chipset_hpt366, |
1629 | .init_iops = init_iops_hpt366, | ||
1649 | .init_hwif = init_hwif_hpt366, | 1630 | .init_hwif = init_hwif_hpt366, |
1650 | .init_dma = init_dma_hpt366, | 1631 | .init_dma = init_dma_hpt366, |
1651 | .channels = 2, | 1632 | .channels = 2, |
@@ -1656,6 +1637,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { | |||
1656 | .name = "HPT372A", | 1637 | .name = "HPT372A", |
1657 | .init_setup = init_setup_hpt37x, | 1638 | .init_setup = init_setup_hpt37x, |
1658 | .init_chipset = init_chipset_hpt366, | 1639 | .init_chipset = init_chipset_hpt366, |
1640 | .init_iops = init_iops_hpt366, | ||
1659 | .init_hwif = init_hwif_hpt366, | 1641 | .init_hwif = init_hwif_hpt366, |
1660 | .init_dma = init_dma_hpt366, | 1642 | .init_dma = init_dma_hpt366, |
1661 | .channels = 2, | 1643 | .channels = 2, |
@@ -1665,6 +1647,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { | |||
1665 | .name = "HPT302", | 1647 | .name = "HPT302", |
1666 | .init_setup = init_setup_hpt37x, | 1648 | .init_setup = init_setup_hpt37x, |
1667 | .init_chipset = init_chipset_hpt366, | 1649 | .init_chipset = init_chipset_hpt366, |
1650 | .init_iops = init_iops_hpt366, | ||
1668 | .init_hwif = init_hwif_hpt366, | 1651 | .init_hwif = init_hwif_hpt366, |
1669 | .init_dma = init_dma_hpt366, | 1652 | .init_dma = init_dma_hpt366, |
1670 | .channels = 2, | 1653 | .channels = 2, |
@@ -1674,6 +1657,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { | |||
1674 | .name = "HPT371", | 1657 | .name = "HPT371", |
1675 | .init_setup = init_setup_hpt37x, | 1658 | .init_setup = init_setup_hpt37x, |
1676 | .init_chipset = init_chipset_hpt366, | 1659 | .init_chipset = init_chipset_hpt366, |
1660 | .init_iops = init_iops_hpt366, | ||
1677 | .init_hwif = init_hwif_hpt366, | 1661 | .init_hwif = init_hwif_hpt366, |
1678 | .init_dma = init_dma_hpt366, | 1662 | .init_dma = init_dma_hpt366, |
1679 | .channels = 2, | 1663 | .channels = 2, |
@@ -1683,6 +1667,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { | |||
1683 | .name = "HPT374", | 1667 | .name = "HPT374", |
1684 | .init_setup = init_setup_hpt374, | 1668 | .init_setup = init_setup_hpt374, |
1685 | .init_chipset = init_chipset_hpt366, | 1669 | .init_chipset = init_chipset_hpt366, |
1670 | .init_iops = init_iops_hpt366, | ||
1686 | .init_hwif = init_hwif_hpt366, | 1671 | .init_hwif = init_hwif_hpt366, |
1687 | .init_dma = init_dma_hpt366, | 1672 | .init_dma = init_dma_hpt366, |
1688 | .channels = 2, /* 4 */ | 1673 | .channels = 2, /* 4 */ |
@@ -1692,6 +1677,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { | |||
1692 | .name = "HPT372N", | 1677 | .name = "HPT372N", |
1693 | .init_setup = init_setup_hpt37x, | 1678 | .init_setup = init_setup_hpt37x, |
1694 | .init_chipset = init_chipset_hpt366, | 1679 | .init_chipset = init_chipset_hpt366, |
1680 | .init_iops = init_iops_hpt366, | ||
1695 | .init_hwif = init_hwif_hpt366, | 1681 | .init_hwif = init_hwif_hpt366, |
1696 | .init_dma = init_dma_hpt366, | 1682 | .init_dma = init_dma_hpt366, |
1697 | .channels = 2, /* 4 */ | 1683 | .channels = 2, /* 4 */ |
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c new file mode 100644 index 000000000000..e440036e651f --- /dev/null +++ b/drivers/ide/pci/it821x.c | |||
@@ -0,0 +1,812 @@ | |||
1 | |||
2 | /* | ||
3 | * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004 | ||
4 | * | ||
5 | * Copyright (C) 2004 Red Hat <alan@redhat.com> | ||
6 | * | ||
7 | * May be copied or modified under the terms of the GNU General Public License | ||
8 | * Based in part on the ITE vendor provided SCSI driver. | ||
9 | * | ||
10 | * Documentation available from | ||
11 | * http://www.ite.com.tw/pc/IT8212F_V04.pdf | ||
12 | * Some other documents are NDA. | ||
13 | * | ||
14 | * The ITE8212 isn't exactly a standard IDE controller. It has two | ||
15 | * modes. In pass through mode then it is an IDE controller. In its smart | ||
16 | * mode its actually quite a capable hardware raid controller disguised | ||
17 | * as an IDE controller. Smart mode only understands DMA read/write and | ||
18 | * identify, none of the fancier commands apply. The IT8211 is identical | ||
19 | * in other respects but lacks the raid mode. | ||
20 | * | ||
21 | * Errata: | ||
22 | * o Rev 0x10 also requires master/slave hold the same DMA timings and | ||
23 | * cannot do ATAPI MWDMA. | ||
24 | * o The identify data for raid volumes lacks CHS info (technically ok) | ||
25 | * but also fails to set the LBA28 and other bits. We fix these in | ||
26 | * the IDE probe quirk code. | ||
27 | * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode | ||
28 | * raid then the controller firmware dies | ||
29 | * o Smart mode without RAID doesn't clear all the necessary identify | ||
30 | * bits to reduce the command set to the one used | ||
31 | * | ||
32 | * This has a few impacts on the driver | ||
33 | * - In pass through mode we do all the work you would expect | ||
34 | * - In smart mode the clocking set up is done by the controller generally | ||
35 | * but we must watch the other limits and filter. | ||
36 | * - There are a few extra vendor commands that actually talk to the | ||
37 | * controller but only work PIO with no IRQ. | ||
38 | * | ||
39 | * Vendor areas of the identify block in smart mode are used for the | ||
40 | * timing and policy set up. Each HDD in raid mode also has a serial | ||
41 | * block on the disk. The hardware extra commands are get/set chip status, | ||
42 | * rebuild, get rebuild status. | ||
43 | * | ||
44 | * In Linux the driver supports pass through mode as if the device was | ||
45 | * just another IDE controller. If the smart mode is running then | ||
46 | * volumes are managed by the controller firmware and each IDE "disk" | ||
47 | * is a raid volume. Even more cute - the controller can do automated | ||
48 | * hotplug and rebuild. | ||
49 | * | ||
50 | * The pass through controller itself is a little demented. It has a | ||
51 | * flaw that it has a single set of PIO/MWDMA timings per channel so | ||
52 | * non UDMA devices restrict each others performance. It also has a | ||
53 | * single clock source per channel so mixed UDMA100/133 performance | ||
54 | * isn't perfect and we have to pick a clock. Thankfully none of this | ||
55 | * matters in smart mode. ATAPI DMA is not currently supported. | ||
56 | * | ||
57 | * It seems the smart mode is a win for RAID1/RAID10 but otherwise not. | ||
58 | * | ||
59 | * TODO | ||
60 | * - ATAPI UDMA is ok but not MWDMA it seems | ||
61 | * - RAID configuration ioctls | ||
62 | * - Move to libata once it grows up | ||
63 | */ | ||
64 | |||
65 | #include <linux/config.h> | ||
66 | #include <linux/types.h> | ||
67 | #include <linux/module.h> | ||
68 | #include <linux/pci.h> | ||
69 | #include <linux/delay.h> | ||
70 | #include <linux/hdreg.h> | ||
71 | #include <linux/ide.h> | ||
72 | #include <linux/init.h> | ||
73 | |||
74 | #include <asm/io.h> | ||
75 | |||
76 | struct it821x_dev | ||
77 | { | ||
78 | unsigned int smart:1, /* Are we in smart raid mode */ | ||
79 | timing10:1; /* Rev 0x10 */ | ||
80 | u8 clock_mode; /* 0, ATA_50 or ATA_66 */ | ||
81 | u8 want[2][2]; /* Mode/Pri log for master slave */ | ||
82 | /* We need these for switching the clock when DMA goes on/off | ||
83 | The high byte is the 66Mhz timing */ | ||
84 | u16 pio[2]; /* Cached PIO values */ | ||
85 | u16 mwdma[2]; /* Cached MWDMA values */ | ||
86 | u16 udma[2]; /* Cached UDMA values (per drive) */ | ||
87 | }; | ||
88 | |||
89 | #define ATA_66 0 | ||
90 | #define ATA_50 1 | ||
91 | #define ATA_ANY 2 | ||
92 | |||
93 | #define UDMA_OFF 0 | ||
94 | #define MWDMA_OFF 0 | ||
95 | |||
96 | /* | ||
97 | * We allow users to force the card into non raid mode without | ||
98 | * flashing the alternative BIOS. This is also neccessary right now | ||
99 | * for embedded platforms that cannot run a PC BIOS but are using this | ||
100 | * device. | ||
101 | */ | ||
102 | |||
103 | static int it8212_noraid; | ||
104 | |||
105 | /** | ||
106 | * it821x_program - program the PIO/MWDMA registers | ||
107 | * @drive: drive to tune | ||
108 | * | ||
109 | * Program the PIO/MWDMA timing for this channel according to the | ||
110 | * current clock. | ||
111 | */ | ||
112 | |||
113 | static void it821x_program(ide_drive_t *drive, u16 timing) | ||
114 | { | ||
115 | ide_hwif_t *hwif = drive->hwif; | ||
116 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
117 | int channel = hwif->channel; | ||
118 | u8 conf; | ||
119 | |||
120 | /* Program PIO/MWDMA timing bits */ | ||
121 | if(itdev->clock_mode == ATA_66) | ||
122 | conf = timing >> 8; | ||
123 | else | ||
124 | conf = timing & 0xFF; | ||
125 | pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf); | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * it821x_program_udma - program the UDMA registers | ||
130 | * @drive: drive to tune | ||
131 | * | ||
132 | * Program the UDMA timing for this drive according to the | ||
133 | * current clock. | ||
134 | */ | ||
135 | |||
136 | static void it821x_program_udma(ide_drive_t *drive, u16 timing) | ||
137 | { | ||
138 | ide_hwif_t *hwif = drive->hwif; | ||
139 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
140 | int channel = hwif->channel; | ||
141 | int unit = drive->select.b.unit; | ||
142 | u8 conf; | ||
143 | |||
144 | /* Program UDMA timing bits */ | ||
145 | if(itdev->clock_mode == ATA_66) | ||
146 | conf = timing >> 8; | ||
147 | else | ||
148 | conf = timing & 0xFF; | ||
149 | if(itdev->timing10 == 0) | ||
150 | pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf); | ||
151 | else { | ||
152 | pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf); | ||
153 | pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | |||
158 | /** | ||
159 | * it821x_clock_strategy | ||
160 | * @hwif: hardware interface | ||
161 | * | ||
162 | * Select between the 50 and 66Mhz base clocks to get the best | ||
163 | * results for this interface. | ||
164 | */ | ||
165 | |||
166 | static void it821x_clock_strategy(ide_drive_t *drive) | ||
167 | { | ||
168 | ide_hwif_t *hwif = drive->hwif; | ||
169 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
170 | |||
171 | u8 unit = drive->select.b.unit; | ||
172 | ide_drive_t *pair = &hwif->drives[1-unit]; | ||
173 | |||
174 | int clock, altclock; | ||
175 | u8 v; | ||
176 | int sel = 0; | ||
177 | |||
178 | if(itdev->want[0][0] > itdev->want[1][0]) { | ||
179 | clock = itdev->want[0][1]; | ||
180 | altclock = itdev->want[1][1]; | ||
181 | } else { | ||
182 | clock = itdev->want[1][1]; | ||
183 | altclock = itdev->want[0][1]; | ||
184 | } | ||
185 | |||
186 | /* Master doesn't care does the slave ? */ | ||
187 | if(clock == ATA_ANY) | ||
188 | clock = altclock; | ||
189 | |||
190 | /* Nobody cares - keep the same clock */ | ||
191 | if(clock == ATA_ANY) | ||
192 | return; | ||
193 | /* No change */ | ||
194 | if(clock == itdev->clock_mode) | ||
195 | return; | ||
196 | |||
197 | /* Load this into the controller ? */ | ||
198 | if(clock == ATA_66) | ||
199 | itdev->clock_mode = ATA_66; | ||
200 | else { | ||
201 | itdev->clock_mode = ATA_50; | ||
202 | sel = 1; | ||
203 | } | ||
204 | pci_read_config_byte(hwif->pci_dev, 0x50, &v); | ||
205 | v &= ~(1 << (1 + hwif->channel)); | ||
206 | v |= sel << (1 + hwif->channel); | ||
207 | pci_write_config_byte(hwif->pci_dev, 0x50, v); | ||
208 | |||
209 | /* | ||
210 | * Reprogram the UDMA/PIO of the pair drive for the switch | ||
211 | * MWDMA will be dealt with by the dma switcher | ||
212 | */ | ||
213 | if(pair && itdev->udma[1-unit] != UDMA_OFF) { | ||
214 | it821x_program_udma(pair, itdev->udma[1-unit]); | ||
215 | it821x_program(pair, itdev->pio[1-unit]); | ||
216 | } | ||
217 | /* | ||
218 | * Reprogram the UDMA/PIO of our drive for the switch. | ||
219 | * MWDMA will be dealt with by the dma switcher | ||
220 | */ | ||
221 | if(itdev->udma[unit] != UDMA_OFF) { | ||
222 | it821x_program_udma(drive, itdev->udma[unit]); | ||
223 | it821x_program(drive, itdev->pio[unit]); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * it821x_ratemask - Compute available modes | ||
229 | * @drive: IDE drive | ||
230 | * | ||
231 | * Compute the available speeds for the devices on the interface. This | ||
232 | * is all modes to ATA133 clipped by drive cable setup. | ||
233 | */ | ||
234 | |||
235 | static u8 it821x_ratemask (ide_drive_t *drive) | ||
236 | { | ||
237 | u8 mode = 4; | ||
238 | if (!eighty_ninty_three(drive)) | ||
239 | mode = min(mode, (u8)1); | ||
240 | return mode; | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * it821x_tuneproc - tune a drive | ||
245 | * @drive: drive to tune | ||
246 | * @mode_wanted: the target operating mode | ||
247 | * | ||
248 | * Load the timing settings for this device mode into the | ||
249 | * controller. By the time we are called the mode has been | ||
250 | * modified as neccessary to handle the absence of seperate | ||
251 | * master/slave timers for MWDMA/PIO. | ||
252 | * | ||
253 | * This code is only used in pass through mode. | ||
254 | */ | ||
255 | |||
256 | static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted) | ||
257 | { | ||
258 | ide_hwif_t *hwif = drive->hwif; | ||
259 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
260 | int unit = drive->select.b.unit; | ||
261 | |||
262 | /* Spec says 89 ref driver uses 88 */ | ||
263 | static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; | ||
264 | static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; | ||
265 | |||
266 | if(itdev->smart) | ||
267 | return; | ||
268 | |||
269 | /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ | ||
270 | itdev->want[unit][1] = pio_want[mode_wanted]; | ||
271 | itdev->want[unit][0] = 1; /* PIO is lowest priority */ | ||
272 | itdev->pio[unit] = pio[mode_wanted]; | ||
273 | it821x_clock_strategy(drive); | ||
274 | it821x_program(drive, itdev->pio[unit]); | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * it821x_tune_mwdma - tune a channel for MWDMA | ||
279 | * @drive: drive to set up | ||
280 | * @mode_wanted: the target operating mode | ||
281 | * | ||
282 | * Load the timing settings for this device mode into the | ||
283 | * controller when doing MWDMA in pass through mode. The caller | ||
284 | * must manage the whole lack of per device MWDMA/PIO timings and | ||
285 | * the shared MWDMA/PIO timing register. | ||
286 | */ | ||
287 | |||
288 | static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted) | ||
289 | { | ||
290 | ide_hwif_t *hwif = drive->hwif; | ||
291 | struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif); | ||
292 | int unit = drive->select.b.unit; | ||
293 | int channel = hwif->channel; | ||
294 | u8 conf; | ||
295 | |||
296 | static u16 dma[] = { 0x8866, 0x3222, 0x3121 }; | ||
297 | static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY }; | ||
298 | |||
299 | itdev->want[unit][1] = mwdma_want[mode_wanted]; | ||
300 | itdev->want[unit][0] = 2; /* MWDMA is low priority */ | ||
301 | itdev->mwdma[unit] = dma[mode_wanted]; | ||
302 | itdev->udma[unit] = UDMA_OFF; | ||
303 | |||
304 | /* UDMA bits off - Revision 0x10 do them in pairs */ | ||
305 | pci_read_config_byte(hwif->pci_dev, 0x50, &conf); | ||
306 | if(itdev->timing10) | ||
307 | conf |= channel ? 0x60: 0x18; | ||
308 | else | ||
309 | conf |= 1 << (3 + 2 * channel + unit); | ||
310 | pci_write_config_byte(hwif->pci_dev, 0x50, conf); | ||
311 | |||
312 | it821x_clock_strategy(drive); | ||
313 | /* FIXME: do we need to program this ? */ | ||
314 | /* it821x_program(drive, itdev->mwdma[unit]); */ | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * it821x_tune_udma - tune a channel for UDMA | ||
319 | * @drive: drive to set up | ||
320 | * @mode_wanted: the target operating mode | ||
321 | * | ||
322 | * Load the timing settings for this device mode into the | ||
323 | * controller when doing UDMA modes in pass through. | ||
324 | */ | ||
325 | |||
326 | static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted) | ||
327 | { | ||
328 | ide_hwif_t *hwif = drive->hwif; | ||
329 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
330 | int unit = drive->select.b.unit; | ||
331 | int channel = hwif->channel; | ||
332 | u8 conf; | ||
333 | |||
334 | static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 }; | ||
335 | static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 }; | ||
336 | |||
337 | itdev->want[unit][1] = udma_want[mode_wanted]; | ||
338 | itdev->want[unit][0] = 3; /* UDMA is high priority */ | ||
339 | itdev->mwdma[unit] = MWDMA_OFF; | ||
340 | itdev->udma[unit] = udma[mode_wanted]; | ||
341 | if(mode_wanted >= 5) | ||
342 | itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */ | ||
343 | |||
344 | /* UDMA on. Again revision 0x10 must do the pair */ | ||
345 | pci_read_config_byte(hwif->pci_dev, 0x50, &conf); | ||
346 | if(itdev->timing10) | ||
347 | conf &= channel ? 0x9F: 0xE7; | ||
348 | else | ||
349 | conf &= ~ (1 << (3 + 2 * channel + unit)); | ||
350 | pci_write_config_byte(hwif->pci_dev, 0x50, conf); | ||
351 | |||
352 | it821x_clock_strategy(drive); | ||
353 | it821x_program_udma(drive, itdev->udma[unit]); | ||
354 | |||
355 | } | ||
356 | |||
357 | /** | ||
358 | * config_it821x_chipset_for_pio - set drive timings | ||
359 | * @drive: drive to tune | ||
360 | * @speed we want | ||
361 | * | ||
362 | * Compute the best pio mode we can for a given device. We must | ||
363 | * pick a speed that does not cause problems with the other device | ||
364 | * on the cable. | ||
365 | */ | ||
366 | |||
367 | static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed) | ||
368 | { | ||
369 | u8 unit = drive->select.b.unit; | ||
370 | ide_hwif_t *hwif = drive->hwif; | ||
371 | ide_drive_t *pair = &hwif->drives[1-unit]; | ||
372 | u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL); | ||
373 | u8 pair_pio; | ||
374 | |||
375 | /* We have to deal with this mess in pairs */ | ||
376 | if(pair != NULL) { | ||
377 | pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL); | ||
378 | /* Trim PIO to the slowest of the master/slave */ | ||
379 | if(pair_pio < set_pio) | ||
380 | set_pio = pair_pio; | ||
381 | } | ||
382 | it821x_tuneproc(drive, set_pio); | ||
383 | speed = XFER_PIO_0 + set_pio; | ||
384 | /* XXX - We trim to the lowest of the pair so the other drive | ||
385 | will always be fine at this point until we do hotplug passthru */ | ||
386 | |||
387 | if (set_speed) | ||
388 | (void) ide_config_drive_speed(drive, speed); | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * it821x_dma_read - DMA hook | ||
393 | * @drive: drive for DMA | ||
394 | * | ||
395 | * The IT821x has a single timing register for MWDMA and for PIO | ||
396 | * operations. As we flip back and forth we have to reload the | ||
397 | * clock. In addition the rev 0x10 device only works if the same | ||
398 | * timing value is loaded into the master and slave UDMA clock | ||
399 | * so we must also reload that. | ||
400 | * | ||
401 | * FIXME: we could figure out in advance if we need to do reloads | ||
402 | */ | ||
403 | |||
404 | static void it821x_dma_start(ide_drive_t *drive) | ||
405 | { | ||
406 | ide_hwif_t *hwif = drive->hwif; | ||
407 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
408 | int unit = drive->select.b.unit; | ||
409 | if(itdev->mwdma[unit] != MWDMA_OFF) | ||
410 | it821x_program(drive, itdev->mwdma[unit]); | ||
411 | else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10) | ||
412 | it821x_program_udma(drive, itdev->udma[unit]); | ||
413 | ide_dma_start(drive); | ||
414 | } | ||
415 | |||
416 | /** | ||
417 | * it821x_dma_write - DMA hook | ||
418 | * @drive: drive for DMA stop | ||
419 | * | ||
420 | * The IT821x has a single timing register for MWDMA and for PIO | ||
421 | * operations. As we flip back and forth we have to reload the | ||
422 | * clock. | ||
423 | */ | ||
424 | |||
425 | static int it821x_dma_end(ide_drive_t *drive) | ||
426 | { | ||
427 | ide_hwif_t *hwif = drive->hwif; | ||
428 | int unit = drive->select.b.unit; | ||
429 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
430 | int ret = __ide_dma_end(drive); | ||
431 | if(itdev->mwdma[unit] != MWDMA_OFF) | ||
432 | it821x_program(drive, itdev->pio[unit]); | ||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | |||
437 | /** | ||
438 | * it821x_tune_chipset - set controller timings | ||
439 | * @drive: Drive to set up | ||
440 | * @xferspeed: speed we want to achieve | ||
441 | * | ||
442 | * Tune the ITE chipset for the desired mode. If we can't achieve | ||
443 | * the desired mode then tune for a lower one, but ultimately | ||
444 | * make the thing work. | ||
445 | */ | ||
446 | |||
447 | static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) | ||
448 | { | ||
449 | |||
450 | ide_hwif_t *hwif = drive->hwif; | ||
451 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
452 | u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); | ||
453 | |||
454 | if(!itdev->smart) { | ||
455 | switch(speed) { | ||
456 | case XFER_PIO_4: | ||
457 | case XFER_PIO_3: | ||
458 | case XFER_PIO_2: | ||
459 | case XFER_PIO_1: | ||
460 | case XFER_PIO_0: | ||
461 | it821x_tuneproc(drive, (speed - XFER_PIO_0)); | ||
462 | break; | ||
463 | /* MWDMA tuning is really hard because our MWDMA and PIO | ||
464 | timings are kept in the same place. We can switch in the | ||
465 | host dma on/off callbacks */ | ||
466 | case XFER_MW_DMA_2: | ||
467 | case XFER_MW_DMA_1: | ||
468 | case XFER_MW_DMA_0: | ||
469 | it821x_tune_mwdma(drive, (speed - XFER_MW_DMA_0)); | ||
470 | break; | ||
471 | case XFER_UDMA_6: | ||
472 | case XFER_UDMA_5: | ||
473 | case XFER_UDMA_4: | ||
474 | case XFER_UDMA_3: | ||
475 | case XFER_UDMA_2: | ||
476 | case XFER_UDMA_1: | ||
477 | case XFER_UDMA_0: | ||
478 | it821x_tune_udma(drive, (speed - XFER_UDMA_0)); | ||
479 | break; | ||
480 | default: | ||
481 | return 1; | ||
482 | } | ||
483 | } | ||
484 | /* | ||
485 | * In smart mode the clocking is done by the host controller | ||
486 | * snooping the mode we picked. The rest of it is not our problem | ||
487 | */ | ||
488 | return ide_config_drive_speed(drive, speed); | ||
489 | } | ||
490 | |||
491 | /** | ||
492 | * config_chipset_for_dma - configure for DMA | ||
493 | * @drive: drive to configure | ||
494 | * | ||
495 | * Called by the IDE layer when it wants the timings set up. | ||
496 | */ | ||
497 | |||
498 | static int config_chipset_for_dma (ide_drive_t *drive) | ||
499 | { | ||
500 | u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); | ||
501 | |||
502 | config_it821x_chipset_for_pio(drive, !speed); | ||
503 | it821x_tune_chipset(drive, speed); | ||
504 | return ide_dma_enable(drive); | ||
505 | } | ||
506 | |||
507 | /** | ||
508 | * it821x_configure_drive_for_dma - set up for DMA transfers | ||
509 | * @drive: drive we are going to set up | ||
510 | * | ||
511 | * Set up the drive for DMA, tune the controller and drive as | ||
512 | * required. If the drive isn't suitable for DMA or we hit | ||
513 | * other problems then we will drop down to PIO and set up | ||
514 | * PIO appropriately | ||
515 | */ | ||
516 | |||
517 | static int it821x_config_drive_for_dma (ide_drive_t *drive) | ||
518 | { | ||
519 | ide_hwif_t *hwif = drive->hwif; | ||
520 | |||
521 | if (ide_use_dma(drive)) { | ||
522 | if (config_chipset_for_dma(drive)) | ||
523 | return hwif->ide_dma_on(drive); | ||
524 | } | ||
525 | config_it821x_chipset_for_pio(drive, 1); | ||
526 | return hwif->ide_dma_off_quietly(drive); | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * ata66_it821x - check for 80 pin cable | ||
531 | * @hwif: interface to check | ||
532 | * | ||
533 | * Check for the presence of an ATA66 capable cable on the | ||
534 | * interface. Problematic as it seems some cards don't have | ||
535 | * the needed logic onboard. | ||
536 | */ | ||
537 | |||
538 | static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif) | ||
539 | { | ||
540 | /* The reference driver also only does disk side */ | ||
541 | return 1; | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * it821x_fixup - post init callback | ||
546 | * @hwif: interface | ||
547 | * | ||
548 | * This callback is run after the drives have been probed but | ||
549 | * before anything gets attached. It allows drivers to do any | ||
550 | * final tuning that is needed, or fixups to work around bugs. | ||
551 | */ | ||
552 | |||
553 | static void __devinit it821x_fixups(ide_hwif_t *hwif) | ||
554 | { | ||
555 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | ||
556 | int i; | ||
557 | |||
558 | if(!itdev->smart) { | ||
559 | /* | ||
560 | * If we are in pass through mode then not much | ||
561 | * needs to be done, but we do bother to clear the | ||
562 | * IRQ mask as we may well be in PIO (eg rev 0x10) | ||
563 | * for now and we know unmasking is safe on this chipset. | ||
564 | */ | ||
565 | for (i = 0; i < 2; i++) { | ||
566 | ide_drive_t *drive = &hwif->drives[i]; | ||
567 | if(drive->present) | ||
568 | drive->unmask = 1; | ||
569 | } | ||
570 | return; | ||
571 | } | ||
572 | /* | ||
573 | * Perform fixups on smart mode. We need to "lose" some | ||
574 | * capabilities the firmware lacks but does not filter, and | ||
575 | * also patch up some capability bits that it forgets to set | ||
576 | * in RAID mode. | ||
577 | */ | ||
578 | |||
579 | for(i = 0; i < 2; i++) { | ||
580 | ide_drive_t *drive = &hwif->drives[i]; | ||
581 | struct hd_driveid *id; | ||
582 | u16 *idbits; | ||
583 | |||
584 | if(!drive->present) | ||
585 | continue; | ||
586 | id = drive->id; | ||
587 | idbits = (u16 *)drive->id; | ||
588 | |||
589 | /* Check for RAID v native */ | ||
590 | if(strstr(id->model, "Integrated Technology Express")) { | ||
591 | /* In raid mode the ident block is slightly buggy | ||
592 | We need to set the bits so that the IDE layer knows | ||
593 | LBA28. LBA48 and DMA ar valid */ | ||
594 | id->capability |= 3; /* LBA28, DMA */ | ||
595 | id->command_set_2 |= 0x0400; /* LBA48 valid */ | ||
596 | id->cfs_enable_2 |= 0x0400; /* LBA48 on */ | ||
597 | /* Reporting logic */ | ||
598 | printk(KERN_INFO "%s: IT8212 %sRAID %d volume", | ||
599 | drive->name, | ||
600 | idbits[147] ? "Bootable ":"", | ||
601 | idbits[129]); | ||
602 | if(idbits[129] != 1) | ||
603 | printk("(%dK stripe)", idbits[146]); | ||
604 | printk(".\n"); | ||
605 | /* Now the core code will have wrongly decided no DMA | ||
606 | so we need to fix this */ | ||
607 | hwif->ide_dma_off_quietly(drive); | ||
608 | #ifdef CONFIG_IDEDMA_ONLYDISK | ||
609 | if (drive->media == ide_disk) | ||
610 | #endif | ||
611 | hwif->ide_dma_check(drive); | ||
612 | } else { | ||
613 | /* Non RAID volume. Fixups to stop the core code | ||
614 | doing unsupported things */ | ||
615 | id->field_valid &= 1; | ||
616 | id->queue_depth = 0; | ||
617 | id->command_set_1 = 0; | ||
618 | id->command_set_2 &= 0xC400; | ||
619 | id->cfsse &= 0xC000; | ||
620 | id->cfs_enable_1 = 0; | ||
621 | id->cfs_enable_2 &= 0xC400; | ||
622 | id->csf_default &= 0xC000; | ||
623 | id->word127 = 0; | ||
624 | id->dlf = 0; | ||
625 | id->csfo = 0; | ||
626 | id->cfa_power = 0; | ||
627 | printk(KERN_INFO "%s: Performing identify fixups.\n", | ||
628 | drive->name); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | } | ||
633 | |||
634 | /** | ||
635 | * init_hwif_it821x - set up hwif structs | ||
636 | * @hwif: interface to set up | ||
637 | * | ||
638 | * We do the basic set up of the interface structure. The IT8212 | ||
639 | * requires several custom handlers so we override the default | ||
640 | * ide DMA handlers appropriately | ||
641 | */ | ||
642 | |||
643 | static void __devinit init_hwif_it821x(ide_hwif_t *hwif) | ||
644 | { | ||
645 | struct it821x_dev *idev = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL); | ||
646 | u8 conf; | ||
647 | |||
648 | if(idev == NULL) { | ||
649 | printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n"); | ||
650 | goto fallback; | ||
651 | } | ||
652 | memset(idev, 0, sizeof(struct it821x_dev)); | ||
653 | ide_set_hwifdata(hwif, idev); | ||
654 | |||
655 | pci_read_config_byte(hwif->pci_dev, 0x50, &conf); | ||
656 | if(conf & 1) { | ||
657 | idev->smart = 1; | ||
658 | hwif->atapi_dma = 0; | ||
659 | /* Long I/O's although allowed in LBA48 space cause the | ||
660 | onboard firmware to enter the twighlight zone */ | ||
661 | hwif->rqsize = 256; | ||
662 | } | ||
663 | |||
664 | /* Pull the current clocks from 0x50 also */ | ||
665 | if (conf & (1 << (1 + hwif->channel))) | ||
666 | idev->clock_mode = ATA_50; | ||
667 | else | ||
668 | idev->clock_mode = ATA_66; | ||
669 | |||
670 | idev->want[0][1] = ATA_ANY; | ||
671 | idev->want[1][1] = ATA_ANY; | ||
672 | |||
673 | /* | ||
674 | * Not in the docs but according to the reference driver | ||
675 | * this is neccessary. | ||
676 | */ | ||
677 | |||
678 | pci_read_config_byte(hwif->pci_dev, 0x08, &conf); | ||
679 | if(conf == 0x10) { | ||
680 | idev->timing10 = 1; | ||
681 | hwif->atapi_dma = 0; | ||
682 | if(!idev->smart) | ||
683 | printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n"); | ||
684 | } | ||
685 | |||
686 | hwif->speedproc = &it821x_tune_chipset; | ||
687 | hwif->tuneproc = &it821x_tuneproc; | ||
688 | |||
689 | /* MWDMA/PIO clock switching for pass through mode */ | ||
690 | if(!idev->smart) { | ||
691 | hwif->dma_start = &it821x_dma_start; | ||
692 | hwif->ide_dma_end = &it821x_dma_end; | ||
693 | } | ||
694 | |||
695 | hwif->drives[0].autotune = 1; | ||
696 | hwif->drives[1].autotune = 1; | ||
697 | |||
698 | if (!hwif->dma_base) | ||
699 | goto fallback; | ||
700 | |||
701 | hwif->ultra_mask = 0x7f; | ||
702 | hwif->mwdma_mask = 0x07; | ||
703 | hwif->swdma_mask = 0x07; | ||
704 | |||
705 | hwif->ide_dma_check = &it821x_config_drive_for_dma; | ||
706 | if (!(hwif->udma_four)) | ||
707 | hwif->udma_four = ata66_it821x(hwif); | ||
708 | |||
709 | /* | ||
710 | * The BIOS often doesn't set up DMA on this controller | ||
711 | * so we always do it. | ||
712 | */ | ||
713 | |||
714 | hwif->autodma = 1; | ||
715 | hwif->drives[0].autodma = hwif->autodma; | ||
716 | hwif->drives[1].autodma = hwif->autodma; | ||
717 | return; | ||
718 | fallback: | ||
719 | hwif->autodma = 0; | ||
720 | return; | ||
721 | } | ||
722 | |||
723 | static void __devinit it8212_disable_raid(struct pci_dev *dev) | ||
724 | { | ||
725 | /* Reset local CPU, and set BIOS not ready */ | ||
726 | pci_write_config_byte(dev, 0x5E, 0x01); | ||
727 | |||
728 | /* Set to bypass mode, and reset PCI bus */ | ||
729 | pci_write_config_byte(dev, 0x50, 0x00); | ||
730 | pci_write_config_word(dev, PCI_COMMAND, | ||
731 | PCI_COMMAND_PARITY | PCI_COMMAND_IO | | ||
732 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | ||
733 | pci_write_config_word(dev, 0x40, 0xA0F3); | ||
734 | |||
735 | pci_write_config_dword(dev,0x4C, 0x02040204); | ||
736 | pci_write_config_byte(dev, 0x42, 0x36); | ||
737 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0); | ||
738 | } | ||
739 | |||
740 | static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name) | ||
741 | { | ||
742 | u8 conf; | ||
743 | static char *mode[2] = { "pass through", "smart" }; | ||
744 | |||
745 | /* Force the card into bypass mode if so requested */ | ||
746 | if (it8212_noraid) { | ||
747 | printk(KERN_INFO "it8212: forcing bypass mode.\n"); | ||
748 | it8212_disable_raid(dev); | ||
749 | } | ||
750 | pci_read_config_byte(dev, 0x50, &conf); | ||
751 | printk(KERN_INFO "it821x: controller in %s mode.\n", mode[conf & 1]); | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | |||
756 | #define DECLARE_ITE_DEV(name_str) \ | ||
757 | { \ | ||
758 | .name = name_str, \ | ||
759 | .init_chipset = init_chipset_it821x, \ | ||
760 | .init_hwif = init_hwif_it821x, \ | ||
761 | .channels = 2, \ | ||
762 | .autodma = AUTODMA, \ | ||
763 | .bootable = ON_BOARD, \ | ||
764 | .fixup = it821x_fixups \ | ||
765 | } | ||
766 | |||
767 | static ide_pci_device_t it821x_chipsets[] __devinitdata = { | ||
768 | /* 0 */ DECLARE_ITE_DEV("IT8212"), | ||
769 | }; | ||
770 | |||
771 | /** | ||
772 | * it821x_init_one - pci layer discovery entry | ||
773 | * @dev: PCI device | ||
774 | * @id: ident table entry | ||
775 | * | ||
776 | * Called by the PCI code when it finds an ITE821x controller. | ||
777 | * We then use the IDE PCI generic helper to do most of the work. | ||
778 | */ | ||
779 | |||
780 | static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) | ||
781 | { | ||
782 | ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | static struct pci_device_id it821x_pci_tbl[] = { | ||
787 | { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
788 | { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
789 | { 0, }, | ||
790 | }; | ||
791 | |||
792 | MODULE_DEVICE_TABLE(pci, it821x_pci_tbl); | ||
793 | |||
794 | static struct pci_driver driver = { | ||
795 | .name = "ITE821x IDE", | ||
796 | .id_table = it821x_pci_tbl, | ||
797 | .probe = it821x_init_one, | ||
798 | }; | ||
799 | |||
800 | static int __init it821x_ide_init(void) | ||
801 | { | ||
802 | return ide_pci_register_driver(&driver); | ||
803 | } | ||
804 | |||
805 | module_init(it821x_ide_init); | ||
806 | |||
807 | module_param_named(noraid, it8212_noraid, int, S_IRUGO); | ||
808 | MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode"); | ||
809 | |||
810 | MODULE_AUTHOR("Alan Cox"); | ||
811 | MODULE_DESCRIPTION("PCI driver module for the ITE 821x"); | ||
812 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index 82a1103b2413..c6f5fa4b4ca6 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c | |||
@@ -442,7 +442,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha | |||
442 | return (dev->irq) ? dev->irq : 0; | 442 | return (dev->irq) ? dev->irq : 0; |
443 | } | 443 | } |
444 | 444 | ||
445 | static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) | 445 | static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif) |
446 | { | 446 | { |
447 | return 1; | 447 | return 1; |
448 | } | 448 | } |
@@ -454,7 +454,7 @@ static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) | |||
454 | * Bit 14 clear = primary IDE channel does not have 80-pin cable. | 454 | * Bit 14 clear = primary IDE channel does not have 80-pin cable. |
455 | * Bit 14 set = primary IDE channel has 80-pin cable. | 455 | * Bit 14 set = primary IDE channel has 80-pin cable. |
456 | */ | 456 | */ |
457 | static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif) | 457 | static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif) |
458 | { | 458 | { |
459 | struct pci_dev *dev = hwif->pci_dev; | 459 | struct pci_dev *dev = hwif->pci_dev; |
460 | if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && | 460 | if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && |
@@ -472,7 +472,7 @@ static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif) | |||
472 | * | 472 | * |
473 | * WARNING: this only works on Alpine hardware! | 473 | * WARNING: this only works on Alpine hardware! |
474 | */ | 474 | */ |
475 | static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif) | 475 | static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif) |
476 | { | 476 | { |
477 | struct pci_dev *dev = hwif->pci_dev; | 477 | struct pci_dev *dev = hwif->pci_dev; |
478 | if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && | 478 | if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && |
@@ -483,7 +483,7 @@ static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif) | |||
483 | return 0; | 483 | return 0; |
484 | } | 484 | } |
485 | 485 | ||
486 | static unsigned int __init ata66_svwks (ide_hwif_t *hwif) | 486 | static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif) |
487 | { | 487 | { |
488 | struct pci_dev *dev = hwif->pci_dev; | 488 | struct pci_dev *dev = hwif->pci_dev; |
489 | 489 | ||
@@ -573,7 +573,7 @@ static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) | |||
573 | return ide_setup_pci_device(dev, d); | 573 | return ide_setup_pci_device(dev, d); |
574 | } | 574 | } |
575 | 575 | ||
576 | static int __init init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d) | 576 | static int __devinit init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d) |
577 | { | 577 | { |
578 | if (!(PCI_FUNC(dev->devfn) & 1)) { | 578 | if (!(PCI_FUNC(dev->devfn) & 1)) { |
579 | d->bootable = NEVER_BOARD; | 579 | d->bootable = NEVER_BOARD; |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index c77a82e46055..3e72c9b1461e 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -17,11 +17,10 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/gameport.h> | 18 | #include <linux/gameport.h> |
19 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
20 | #include <linux/completion.h> | ||
21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
24 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/kthread.h> | ||
25 | 24 | ||
26 | /*#include <asm/io.h>*/ | 25 | /*#include <asm/io.h>*/ |
27 | 26 | ||
@@ -238,8 +237,7 @@ struct gameport_event { | |||
238 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ | 237 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ |
239 | static LIST_HEAD(gameport_event_list); | 238 | static LIST_HEAD(gameport_event_list); |
240 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); | 239 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); |
241 | static DECLARE_COMPLETION(gameport_exited); | 240 | static struct task_struct *gameport_task; |
242 | static int gameport_pid; | ||
243 | 241 | ||
244 | static void gameport_queue_event(void *object, struct module *owner, | 242 | static void gameport_queue_event(void *object, struct module *owner, |
245 | enum gameport_event_type event_type) | 243 | enum gameport_event_type event_type) |
@@ -250,12 +248,12 @@ static void gameport_queue_event(void *object, struct module *owner, | |||
250 | spin_lock_irqsave(&gameport_event_lock, flags); | 248 | spin_lock_irqsave(&gameport_event_lock, flags); |
251 | 249 | ||
252 | /* | 250 | /* |
253 | * Scan event list for the other events for the same gameport port, | 251 | * Scan event list for the other events for the same gameport port, |
254 | * starting with the most recent one. If event is the same we | 252 | * starting with the most recent one. If event is the same we |
255 | * do not need add new one. If event is of different type we | 253 | * do not need add new one. If event is of different type we |
256 | * need to add this event and should not look further because | 254 | * need to add this event and should not look further because |
257 | * we need to preseve sequence of distinct events. | 255 | * we need to preseve sequence of distinct events. |
258 | */ | 256 | */ |
259 | list_for_each_entry_reverse(event, &gameport_event_list, node) { | 257 | list_for_each_entry_reverse(event, &gameport_event_list, node) { |
260 | if (event->object == object) { | 258 | if (event->object == object) { |
261 | if (event->type == event_type) | 259 | if (event->type == event_type) |
@@ -432,20 +430,15 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent) | |||
432 | 430 | ||
433 | static int gameport_thread(void *nothing) | 431 | static int gameport_thread(void *nothing) |
434 | { | 432 | { |
435 | lock_kernel(); | ||
436 | daemonize("kgameportd"); | ||
437 | allow_signal(SIGTERM); | ||
438 | |||
439 | do { | 433 | do { |
440 | gameport_handle_events(); | 434 | gameport_handle_events(); |
441 | wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list)); | 435 | wait_event_interruptible(gameport_wait, |
436 | kthread_should_stop() || !list_empty(&gameport_event_list)); | ||
442 | try_to_freeze(); | 437 | try_to_freeze(); |
443 | } while (!signal_pending(current)); | 438 | } while (!kthread_should_stop()); |
444 | 439 | ||
445 | printk(KERN_DEBUG "gameport: kgameportd exiting\n"); | 440 | printk(KERN_DEBUG "gameport: kgameportd exiting\n"); |
446 | 441 | return 0; | |
447 | unlock_kernel(); | ||
448 | complete_and_exit(&gameport_exited, 0); | ||
449 | } | 442 | } |
450 | 443 | ||
451 | 444 | ||
@@ -773,9 +766,10 @@ void gameport_close(struct gameport *gameport) | |||
773 | 766 | ||
774 | static int __init gameport_init(void) | 767 | static int __init gameport_init(void) |
775 | { | 768 | { |
776 | if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) { | 769 | gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); |
770 | if (IS_ERR(gameport_task)) { | ||
777 | printk(KERN_ERR "gameport: Failed to start kgameportd\n"); | 771 | printk(KERN_ERR "gameport: Failed to start kgameportd\n"); |
778 | return -1; | 772 | return PTR_ERR(gameport_task); |
779 | } | 773 | } |
780 | 774 | ||
781 | gameport_bus.dev_attrs = gameport_device_attrs; | 775 | gameport_bus.dev_attrs = gameport_device_attrs; |
@@ -789,8 +783,7 @@ static int __init gameport_init(void) | |||
789 | static void __exit gameport_exit(void) | 783 | static void __exit gameport_exit(void) |
790 | { | 784 | { |
791 | bus_unregister(&gameport_bus); | 785 | bus_unregister(&gameport_bus); |
792 | kill_proc(gameport_pid, SIGTERM, 1); | 786 | kthread_stop(gameport_task); |
793 | wait_for_completion(&gameport_exited); | ||
794 | } | 787 | } |
795 | 788 | ||
796 | module_init(gameport_init); | 789 | module_init(gameport_init); |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 341824c48529..f367695e69b5 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -31,10 +31,9 @@ | |||
31 | #include <linux/serio.h> | 31 | #include <linux/serio.h> |
32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
34 | #include <linux/completion.h> | ||
35 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
36 | #include <linux/smp_lock.h> | ||
37 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/kthread.h> | ||
38 | 37 | ||
39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 38 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
40 | MODULE_DESCRIPTION("Serio abstraction core"); | 39 | MODULE_DESCRIPTION("Serio abstraction core"); |
@@ -43,6 +42,7 @@ MODULE_LICENSE("GPL"); | |||
43 | EXPORT_SYMBOL(serio_interrupt); | 42 | EXPORT_SYMBOL(serio_interrupt); |
44 | EXPORT_SYMBOL(__serio_register_port); | 43 | EXPORT_SYMBOL(__serio_register_port); |
45 | EXPORT_SYMBOL(serio_unregister_port); | 44 | EXPORT_SYMBOL(serio_unregister_port); |
45 | EXPORT_SYMBOL(serio_unregister_child_port); | ||
46 | EXPORT_SYMBOL(__serio_unregister_port_delayed); | 46 | EXPORT_SYMBOL(__serio_unregister_port_delayed); |
47 | EXPORT_SYMBOL(__serio_register_driver); | 47 | EXPORT_SYMBOL(__serio_register_driver); |
48 | EXPORT_SYMBOL(serio_unregister_driver); | 48 | EXPORT_SYMBOL(serio_unregister_driver); |
@@ -68,6 +68,37 @@ static void serio_destroy_port(struct serio *serio); | |||
68 | static void serio_reconnect_port(struct serio *serio); | 68 | static void serio_reconnect_port(struct serio *serio); |
69 | static void serio_disconnect_port(struct serio *serio); | 69 | static void serio_disconnect_port(struct serio *serio); |
70 | 70 | ||
71 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) | ||
72 | { | ||
73 | int retval; | ||
74 | |||
75 | down(&serio->drv_sem); | ||
76 | retval = drv->connect(serio, drv); | ||
77 | up(&serio->drv_sem); | ||
78 | |||
79 | return retval; | ||
80 | } | ||
81 | |||
82 | static int serio_reconnect_driver(struct serio *serio) | ||
83 | { | ||
84 | int retval = -1; | ||
85 | |||
86 | down(&serio->drv_sem); | ||
87 | if (serio->drv && serio->drv->reconnect) | ||
88 | retval = serio->drv->reconnect(serio); | ||
89 | up(&serio->drv_sem); | ||
90 | |||
91 | return retval; | ||
92 | } | ||
93 | |||
94 | static void serio_disconnect_driver(struct serio *serio) | ||
95 | { | ||
96 | down(&serio->drv_sem); | ||
97 | if (serio->drv) | ||
98 | serio->drv->disconnect(serio); | ||
99 | up(&serio->drv_sem); | ||
100 | } | ||
101 | |||
71 | static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) | 102 | static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) |
72 | { | 103 | { |
73 | while (ids->type || ids->proto) { | 104 | while (ids->type || ids->proto) { |
@@ -91,7 +122,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) | |||
91 | 122 | ||
92 | if (serio_match_port(drv->id_table, serio)) { | 123 | if (serio_match_port(drv->id_table, serio)) { |
93 | serio->dev.driver = &drv->driver; | 124 | serio->dev.driver = &drv->driver; |
94 | if (drv->connect(serio, drv)) { | 125 | if (serio_connect_driver(serio, drv)) { |
95 | serio->dev.driver = NULL; | 126 | serio->dev.driver = NULL; |
96 | goto out; | 127 | goto out; |
97 | } | 128 | } |
@@ -138,8 +169,7 @@ struct serio_event { | |||
138 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ | 169 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ |
139 | static LIST_HEAD(serio_event_list); | 170 | static LIST_HEAD(serio_event_list); |
140 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); | 171 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); |
141 | static DECLARE_COMPLETION(serio_exited); | 172 | static struct task_struct *serio_task; |
142 | static int serio_pid; | ||
143 | 173 | ||
144 | static void serio_queue_event(void *object, struct module *owner, | 174 | static void serio_queue_event(void *object, struct module *owner, |
145 | enum serio_event_type event_type) | 175 | enum serio_event_type event_type) |
@@ -150,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner, | |||
150 | spin_lock_irqsave(&serio_event_lock, flags); | 180 | spin_lock_irqsave(&serio_event_lock, flags); |
151 | 181 | ||
152 | /* | 182 | /* |
153 | * Scan event list for the other events for the same serio port, | 183 | * Scan event list for the other events for the same serio port, |
154 | * starting with the most recent one. If event is the same we | 184 | * starting with the most recent one. If event is the same we |
155 | * do not need add new one. If event is of different type we | 185 | * do not need add new one. If event is of different type we |
156 | * need to add this event and should not look further because | 186 | * need to add this event and should not look further because |
157 | * we need to preseve sequence of distinct events. | 187 | * we need to preseve sequence of distinct events. |
158 | */ | 188 | */ |
159 | list_for_each_entry_reverse(event, &serio_event_list, node) { | 189 | list_for_each_entry_reverse(event, &serio_event_list, node) { |
160 | if (event->object == object) { | 190 | if (event->object == object) { |
161 | if (event->type == event_type) | 191 | if (event->type == event_type) |
@@ -337,20 +367,15 @@ static struct serio *serio_get_pending_child(struct serio *parent) | |||
337 | 367 | ||
338 | static int serio_thread(void *nothing) | 368 | static int serio_thread(void *nothing) |
339 | { | 369 | { |
340 | lock_kernel(); | ||
341 | daemonize("kseriod"); | ||
342 | allow_signal(SIGTERM); | ||
343 | |||
344 | do { | 370 | do { |
345 | serio_handle_events(); | 371 | serio_handle_events(); |
346 | wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); | 372 | wait_event_interruptible(serio_wait, |
373 | kthread_should_stop() || !list_empty(&serio_event_list)); | ||
347 | try_to_freeze(); | 374 | try_to_freeze(); |
348 | } while (!signal_pending(current)); | 375 | } while (!kthread_should_stop()); |
349 | 376 | ||
350 | printk(KERN_DEBUG "serio: kseriod exiting\n"); | 377 | printk(KERN_DEBUG "serio: kseriod exiting\n"); |
351 | 378 | return 0; | |
352 | unlock_kernel(); | ||
353 | complete_and_exit(&serio_exited, 0); | ||
354 | } | 379 | } |
355 | 380 | ||
356 | 381 | ||
@@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio) | |||
557 | static void serio_reconnect_port(struct serio *serio) | 582 | static void serio_reconnect_port(struct serio *serio) |
558 | { | 583 | { |
559 | do { | 584 | do { |
560 | if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { | 585 | if (serio_reconnect_driver(serio)) { |
561 | serio_disconnect_port(serio); | 586 | serio_disconnect_port(serio); |
562 | serio_find_driver(serio); | 587 | serio_find_driver(serio); |
563 | /* Ok, old children are now gone, we are done */ | 588 | /* Ok, old children are now gone, we are done */ |
@@ -630,6 +655,19 @@ void serio_unregister_port(struct serio *serio) | |||
630 | } | 655 | } |
631 | 656 | ||
632 | /* | 657 | /* |
658 | * Safely unregisters child port if one is present. | ||
659 | */ | ||
660 | void serio_unregister_child_port(struct serio *serio) | ||
661 | { | ||
662 | down(&serio_sem); | ||
663 | if (serio->child) { | ||
664 | serio_disconnect_port(serio->child); | ||
665 | serio_destroy_port(serio->child); | ||
666 | } | ||
667 | up(&serio_sem); | ||
668 | } | ||
669 | |||
670 | /* | ||
633 | * Submits register request to kseriod for subsequent execution. | 671 | * Submits register request to kseriod for subsequent execution. |
634 | * Can be used when it is not obvious whether the serio_sem is | 672 | * Can be used when it is not obvious whether the serio_sem is |
635 | * taken or not and when delayed execution is feasible. | 673 | * taken or not and when delayed execution is feasible. |
@@ -686,15 +724,14 @@ static int serio_driver_probe(struct device *dev) | |||
686 | struct serio *serio = to_serio_port(dev); | 724 | struct serio *serio = to_serio_port(dev); |
687 | struct serio_driver *drv = to_serio_driver(dev->driver); | 725 | struct serio_driver *drv = to_serio_driver(dev->driver); |
688 | 726 | ||
689 | return drv->connect(serio, drv); | 727 | return serio_connect_driver(serio, drv); |
690 | } | 728 | } |
691 | 729 | ||
692 | static int serio_driver_remove(struct device *dev) | 730 | static int serio_driver_remove(struct device *dev) |
693 | { | 731 | { |
694 | struct serio *serio = to_serio_port(dev); | 732 | struct serio *serio = to_serio_port(dev); |
695 | struct serio_driver *drv = to_serio_driver(dev->driver); | ||
696 | 733 | ||
697 | drv->disconnect(serio); | 734 | serio_disconnect_driver(serio); |
698 | return 0; | 735 | return 0; |
699 | } | 736 | } |
700 | 737 | ||
@@ -730,11 +767,9 @@ start_over: | |||
730 | 767 | ||
731 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) | 768 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) |
732 | { | 769 | { |
733 | down(&serio->drv_sem); | ||
734 | serio_pause_rx(serio); | 770 | serio_pause_rx(serio); |
735 | serio->drv = drv; | 771 | serio->drv = drv; |
736 | serio_continue_rx(serio); | 772 | serio_continue_rx(serio); |
737 | up(&serio->drv_sem); | ||
738 | } | 773 | } |
739 | 774 | ||
740 | static int serio_bus_match(struct device *dev, struct device_driver *drv) | 775 | static int serio_bus_match(struct device *dev, struct device_driver *drv) |
@@ -794,7 +829,7 @@ static int serio_resume(struct device *dev) | |||
794 | { | 829 | { |
795 | struct serio *serio = to_serio_port(dev); | 830 | struct serio *serio = to_serio_port(dev); |
796 | 831 | ||
797 | if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { | 832 | if (serio_reconnect_driver(serio)) { |
798 | /* | 833 | /* |
799 | * Driver re-probing can take a while, so better let kseriod | 834 | * Driver re-probing can take a while, so better let kseriod |
800 | * deal with it. | 835 | * deal with it. |
@@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio, | |||
848 | 883 | ||
849 | static int __init serio_init(void) | 884 | static int __init serio_init(void) |
850 | { | 885 | { |
851 | if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) { | 886 | serio_task = kthread_run(serio_thread, NULL, "kseriod"); |
887 | if (IS_ERR(serio_task)) { | ||
852 | printk(KERN_ERR "serio: Failed to start kseriod\n"); | 888 | printk(KERN_ERR "serio: Failed to start kseriod\n"); |
853 | return -1; | 889 | return PTR_ERR(serio_task); |
854 | } | 890 | } |
855 | 891 | ||
856 | serio_bus.dev_attrs = serio_device_attrs; | 892 | serio_bus.dev_attrs = serio_device_attrs; |
@@ -866,8 +902,7 @@ static int __init serio_init(void) | |||
866 | static void __exit serio_exit(void) | 902 | static void __exit serio_exit(void) |
867 | { | 903 | { |
868 | bus_unregister(&serio_bus); | 904 | bus_unregister(&serio_bus); |
869 | kill_proc(serio_pid, SIGTERM, 1); | 905 | kthread_stop(serio_task); |
870 | wait_for_completion(&serio_exited); | ||
871 | } | 906 | } |
872 | 907 | ||
873 | module_init(serio_init); | 908 | module_init(serio_init); |
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index dc00c85e3e35..ee750e9456dd 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c | |||
@@ -486,6 +486,14 @@ static int avmcs_event(event_t event, int priority, | |||
486 | return 0; | 486 | return 0; |
487 | } /* avmcs_event */ | 487 | } /* avmcs_event */ |
488 | 488 | ||
489 | static struct pcmcia_device_id avmcs_ids[] = { | ||
490 | PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), | ||
491 | PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430), | ||
492 | PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a), | ||
493 | PCMCIA_DEVICE_NULL | ||
494 | }; | ||
495 | MODULE_DEVICE_TABLE(pcmcia, avmcs_ids); | ||
496 | |||
489 | static struct pcmcia_driver avmcs_driver = { | 497 | static struct pcmcia_driver avmcs_driver = { |
490 | .owner = THIS_MODULE, | 498 | .owner = THIS_MODULE, |
491 | .drv = { | 499 | .drv = { |
@@ -493,6 +501,7 @@ static struct pcmcia_driver avmcs_driver = { | |||
493 | }, | 501 | }, |
494 | .attach = avmcs_attach, | 502 | .attach = avmcs_attach, |
495 | .detach = avmcs_detach, | 503 | .detach = avmcs_detach, |
504 | .id_table = avmcs_ids, | ||
496 | }; | 505 | }; |
497 | 506 | ||
498 | static int __init avmcs_init(void) | 507 | static int __init avmcs_init(void) |
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 663a0bf703b7..67c60e04a37b 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c | |||
@@ -501,6 +501,13 @@ static int avma1cs_event(event_t event, int priority, | |||
501 | return 0; | 501 | return 0; |
502 | } /* avma1cs_event */ | 502 | } /* avma1cs_event */ |
503 | 503 | ||
504 | static struct pcmcia_device_id avma1cs_ids[] = { | ||
505 | PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), | ||
506 | PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b), | ||
507 | PCMCIA_DEVICE_NULL | ||
508 | }; | ||
509 | MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids); | ||
510 | |||
504 | static struct pcmcia_driver avma1cs_driver = { | 511 | static struct pcmcia_driver avma1cs_driver = { |
505 | .owner = THIS_MODULE, | 512 | .owner = THIS_MODULE, |
506 | .drv = { | 513 | .drv = { |
@@ -508,6 +515,7 @@ static struct pcmcia_driver avma1cs_driver = { | |||
508 | }, | 515 | }, |
509 | .attach = avma1cs_attach, | 516 | .attach = avma1cs_attach, |
510 | .detach = avma1cs_detach, | 517 | .detach = avma1cs_detach, |
518 | .id_table = avma1cs_ids, | ||
511 | }; | 519 | }; |
512 | 520 | ||
513 | /*====================================================================*/ | 521 | /*====================================================================*/ |
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index bfc013225f46..9146be547044 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c | |||
@@ -508,6 +508,13 @@ static int elsa_cs_event(event_t event, int priority, | |||
508 | return 0; | 508 | return 0; |
509 | } /* elsa_cs_event */ | 509 | } /* elsa_cs_event */ |
510 | 510 | ||
511 | static struct pcmcia_device_id elsa_ids[] = { | ||
512 | PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257), | ||
513 | PCMCIA_DEVICE_PROD_ID12("ELSA GmbH, Aachen", "MicroLink ISDN/MC ", 0x639e5718, 0x333ba257), | ||
514 | PCMCIA_DEVICE_NULL | ||
515 | }; | ||
516 | MODULE_DEVICE_TABLE(pcmcia, elsa_ids); | ||
517 | |||
511 | static struct pcmcia_driver elsa_cs_driver = { | 518 | static struct pcmcia_driver elsa_cs_driver = { |
512 | .owner = THIS_MODULE, | 519 | .owner = THIS_MODULE, |
513 | .drv = { | 520 | .drv = { |
@@ -515,6 +522,7 @@ static struct pcmcia_driver elsa_cs_driver = { | |||
515 | }, | 522 | }, |
516 | .attach = elsa_cs_attach, | 523 | .attach = elsa_cs_attach, |
517 | .detach = elsa_cs_detach, | 524 | .detach = elsa_cs_detach, |
525 | .id_table = elsa_ids, | ||
518 | }; | 526 | }; |
519 | 527 | ||
520 | static int __init init_elsa_cs(void) | 528 | static int __init init_elsa_cs(void) |
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 449651241477..058147a69576 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -616,6 +616,18 @@ static int sedlbauer_event(event_t event, int priority, | |||
616 | return 0; | 616 | return 0; |
617 | } /* sedlbauer_event */ | 617 | } /* sedlbauer_event */ |
618 | 618 | ||
619 | static struct pcmcia_device_id sedlbauer_ids[] = { | ||
620 | PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c), | ||
621 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90), | ||
622 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce), | ||
623 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe), | ||
624 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (c) 93-95 VK", 0x81fb79f5, 0xe4e9bc12, 0xb391ab4c), | ||
625 | PCMCIA_DEVICE_PROD_ID12("HST High Soft Tech GmbH", "Saphir II B", 0xd79e0b84, 0x21d083ae), | ||
626 | /* PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", 0x81fb79f5), */ /* too generic*/ | ||
627 | PCMCIA_DEVICE_NULL | ||
628 | }; | ||
629 | MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids); | ||
630 | |||
619 | static struct pcmcia_driver sedlbauer_driver = { | 631 | static struct pcmcia_driver sedlbauer_driver = { |
620 | .owner = THIS_MODULE, | 632 | .owner = THIS_MODULE, |
621 | .drv = { | 633 | .drv = { |
@@ -623,6 +635,7 @@ static struct pcmcia_driver sedlbauer_driver = { | |||
623 | }, | 635 | }, |
624 | .attach = sedlbauer_attach, | 636 | .attach = sedlbauer_attach, |
625 | .detach = sedlbauer_detach, | 637 | .detach = sedlbauer_detach, |
638 | .id_table = sedlbauer_ids, | ||
626 | }; | 639 | }; |
627 | 640 | ||
628 | static int __init init_sedlbauer_cs(void) | 641 | static int __init init_sedlbauer_cs(void) |
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 63e8e20c17a8..107376ff5b9b 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c | |||
@@ -489,6 +489,12 @@ static int teles_cs_event(event_t event, int priority, | |||
489 | return 0; | 489 | return 0; |
490 | } /* teles_cs_event */ | 490 | } /* teles_cs_event */ |
491 | 491 | ||
492 | static struct pcmcia_device_id teles_ids[] = { | ||
493 | PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119), | ||
494 | PCMCIA_DEVICE_NULL, | ||
495 | }; | ||
496 | MODULE_DEVICE_TABLE(pcmcia, teles_ids); | ||
497 | |||
492 | static struct pcmcia_driver teles_cs_driver = { | 498 | static struct pcmcia_driver teles_cs_driver = { |
493 | .owner = THIS_MODULE, | 499 | .owner = THIS_MODULE, |
494 | .drv = { | 500 | .drv = { |
@@ -496,6 +502,7 @@ static struct pcmcia_driver teles_cs_driver = { | |||
496 | }, | 502 | }, |
497 | .attach = teles_attach, | 503 | .attach = teles_attach, |
498 | .detach = teles_detach, | 504 | .detach = teles_detach, |
505 | .id_table = teles_ids, | ||
499 | }; | 506 | }; |
500 | 507 | ||
501 | static int __init init_teles_cs(void) | 508 | static int __init init_teles_cs(void) |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 8480057eadb4..2bea2e0b06f2 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -607,6 +607,16 @@ config MTD_PCMCIA | |||
607 | cards are usually around 4-16MiB in size. This does not include | 607 | cards are usually around 4-16MiB in size. This does not include |
608 | Compact Flash cards which are treated as IDE devices. | 608 | Compact Flash cards which are treated as IDE devices. |
609 | 609 | ||
610 | config MTD_PCMCIA_ANONYMOUS | ||
611 | bool "Use PCMCIA MTD drivers for anonymous PCMCIA cards" | ||
612 | depends on MTD_PCMCIA | ||
613 | default N | ||
614 | help | ||
615 | If this option is enabled, PCMCIA cards which do not report | ||
616 | anything about themselves are assumed to be MTD cards. | ||
617 | |||
618 | If unsure, say N. | ||
619 | |||
610 | config MTD_UCLINUX | 620 | config MTD_UCLINUX |
611 | tristate "Generic uClinux RAM/ROM filesystem support" | 621 | tristate "Generic uClinux RAM/ROM filesystem support" |
612 | depends on MTD_PARTITIONS && !MMU | 622 | depends on MTD_PARTITIONS && !MMU |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index e37b4c1976e5..c2655a817e3d 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -818,6 +818,32 @@ static dev_link_t *pcmciamtd_attach(void) | |||
818 | return link; | 818 | return link; |
819 | } | 819 | } |
820 | 820 | ||
821 | static struct pcmcia_device_id pcmciamtd_ids[] = { | ||
822 | PCMCIA_DEVICE_FUNC_ID(1), | ||
823 | PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCS-2M", "2MB SRAM", 0x547e66dc, 0x1fed36cd, 0x36eadd21), | ||
824 | PCMCIA_DEVICE_PROD_ID12("IBM", "2MB SRAM", 0xb569a6e5, 0x36eadd21), | ||
825 | PCMCIA_DEVICE_PROD_ID12("IBM", "4MB FLASH", 0xb569a6e5, 0x8bc54d2a), | ||
826 | PCMCIA_DEVICE_PROD_ID12("IBM", "8MB FLASH", 0xb569a6e5, 0x6df1be3e), | ||
827 | PCMCIA_DEVICE_PROD_ID12("Intel", "S2E20SW", 0x816cc815, 0xd14c9dcf), | ||
828 | PCMCIA_DEVICE_PROD_ID12("Intel", "S2E8 SW", 0x816cc815, 0xa2d7dedb), | ||
829 | PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-02 ", 0x40ade711, 0x145cea5c), | ||
830 | PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-04 ", 0x40ade711, 0x42064dda), | ||
831 | PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-20 ", 0x40ade711, 0x25ee5cb0), | ||
832 | PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8), | ||
833 | PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c), | ||
834 | PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0), | ||
835 | PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b), | ||
836 | PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad), | ||
837 | PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca), | ||
838 | PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944), | ||
839 | /* the following was commented out in pcmcia-cs-3.2.7 */ | ||
840 | /* PCMCIA_DEVICE_PROD_ID12("RATOC Systems,Inc.", "SmartMedia ADAPTER PC Card", 0xf4a2fefe, 0x5885b2ae), */ | ||
841 | #ifdef CONFIG_MTD_PCMCIA_ANONYMOUS | ||
842 | { .match_flags = PCMCIA_DEV_ID_MATCH_ANONYMOUS, }, | ||
843 | #endif | ||
844 | PCMCIA_DEVICE_NULL | ||
845 | }; | ||
846 | MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids); | ||
821 | 847 | ||
822 | static struct pcmcia_driver pcmciamtd_driver = { | 848 | static struct pcmcia_driver pcmciamtd_driver = { |
823 | .drv = { | 849 | .drv = { |
@@ -825,7 +851,8 @@ static struct pcmcia_driver pcmciamtd_driver = { | |||
825 | }, | 851 | }, |
826 | .attach = pcmciamtd_attach, | 852 | .attach = pcmciamtd_attach, |
827 | .detach = pcmciamtd_detach, | 853 | .detach = pcmciamtd_detach, |
828 | .owner = THIS_MODULE | 854 | .owner = THIS_MODULE, |
855 | .id_table = pcmciamtd_ids, | ||
829 | }; | 856 | }; |
830 | 857 | ||
831 | 858 | ||
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index c6e8b25f9685..f0fc04bd37c4 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -1286,6 +1286,13 @@ static int el3_close(struct net_device *dev) | |||
1286 | return 0; | 1286 | return 0; |
1287 | } | 1287 | } |
1288 | 1288 | ||
1289 | static struct pcmcia_device_id tc574_ids[] = { | ||
1290 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), | ||
1291 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"), | ||
1292 | PCMCIA_DEVICE_NULL, | ||
1293 | }; | ||
1294 | MODULE_DEVICE_TABLE(pcmcia, tc574_ids); | ||
1295 | |||
1289 | static struct pcmcia_driver tc574_driver = { | 1296 | static struct pcmcia_driver tc574_driver = { |
1290 | .owner = THIS_MODULE, | 1297 | .owner = THIS_MODULE, |
1291 | .drv = { | 1298 | .drv = { |
@@ -1293,6 +1300,7 @@ static struct pcmcia_driver tc574_driver = { | |||
1293 | }, | 1300 | }, |
1294 | .attach = tc574_attach, | 1301 | .attach = tc574_attach, |
1295 | .detach = tc574_detach, | 1302 | .detach = tc574_detach, |
1303 | .id_table = tc574_ids, | ||
1296 | }; | 1304 | }; |
1297 | 1305 | ||
1298 | static int __init init_tc574(void) | 1306 | static int __init init_tc574(void) |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 89abdda1d343..8fa1b5f0fb68 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -1057,6 +1057,17 @@ static int el3_close(struct net_device *dev) | |||
1057 | return 0; | 1057 | return 0; |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | static struct pcmcia_device_id tc589_ids[] = { | ||
1061 | PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), | ||
1062 | PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), | ||
1063 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), | ||
1064 | PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), | ||
1065 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"), | ||
1066 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"), | ||
1067 | PCMCIA_DEVICE_NULL, | ||
1068 | }; | ||
1069 | MODULE_DEVICE_TABLE(pcmcia, tc589_ids); | ||
1070 | |||
1060 | static struct pcmcia_driver tc589_driver = { | 1071 | static struct pcmcia_driver tc589_driver = { |
1061 | .owner = THIS_MODULE, | 1072 | .owner = THIS_MODULE, |
1062 | .drv = { | 1073 | .drv = { |
@@ -1064,6 +1075,7 @@ static struct pcmcia_driver tc589_driver = { | |||
1064 | }, | 1075 | }, |
1065 | .attach = tc589_attach, | 1076 | .attach = tc589_attach, |
1066 | .detach = tc589_detach, | 1077 | .detach = tc589_detach, |
1078 | .id_table = tc589_ids, | ||
1067 | }; | 1079 | }; |
1068 | 1080 | ||
1069 | static int __init init_tc589(void) | 1081 | static int __init init_tc589(void) |
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 853b586e481a..23ce77b1d5b0 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -850,6 +850,34 @@ static void block_output(struct net_device *dev, int count, | |||
850 | outsw(nic_base + AXNET_DATAPORT, buf, count>>1); | 850 | outsw(nic_base + AXNET_DATAPORT, buf, count>>1); |
851 | } | 851 | } |
852 | 852 | ||
853 | static struct pcmcia_device_id axnet_ids[] = { | ||
854 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081), | ||
855 | PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301), | ||
856 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301), | ||
857 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303), | ||
858 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309), | ||
859 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106), | ||
860 | PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), | ||
861 | PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef), | ||
862 | PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef), | ||
863 | PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1), | ||
864 | PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc), | ||
865 | PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b), | ||
866 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5), | ||
867 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e), | ||
868 | PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90), | ||
869 | PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8), | ||
870 | PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609), | ||
871 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04), | ||
872 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116), | ||
873 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058), | ||
874 | PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6, 0xab9be5ef), | ||
875 | /* this is not specific enough */ | ||
876 | /* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), */ | ||
877 | PCMCIA_DEVICE_NULL, | ||
878 | }; | ||
879 | MODULE_DEVICE_TABLE(pcmcia, axnet_ids); | ||
880 | |||
853 | static struct pcmcia_driver axnet_cs_driver = { | 881 | static struct pcmcia_driver axnet_cs_driver = { |
854 | .owner = THIS_MODULE, | 882 | .owner = THIS_MODULE, |
855 | .drv = { | 883 | .drv = { |
@@ -857,6 +885,7 @@ static struct pcmcia_driver axnet_cs_driver = { | |||
857 | }, | 885 | }, |
858 | .attach = axnet_attach, | 886 | .attach = axnet_attach, |
859 | .detach = axnet_detach, | 887 | .detach = axnet_detach, |
888 | .id_table = axnet_ids, | ||
860 | }; | 889 | }; |
861 | 890 | ||
862 | static int __init init_axnet_cs(void) | 891 | static int __init init_axnet_cs(void) |
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 4294e1e3f156..68d58cc58d31 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -483,7 +483,11 @@ static int com20020_event(event_t event, int priority, | |||
483 | return 0; | 483 | return 0; |
484 | } /* com20020_event */ | 484 | } /* com20020_event */ |
485 | 485 | ||
486 | 486 | static struct pcmcia_device_id com20020_ids[] = { | |
487 | PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), | ||
488 | PCMCIA_DEVICE_NULL | ||
489 | }; | ||
490 | MODULE_DEVICE_TABLE(pcmcia, com20020_ids); | ||
487 | 491 | ||
488 | static struct pcmcia_driver com20020_cs_driver = { | 492 | static struct pcmcia_driver com20020_cs_driver = { |
489 | .owner = THIS_MODULE, | 493 | .owner = THIS_MODULE, |
@@ -492,6 +496,7 @@ static struct pcmcia_driver com20020_cs_driver = { | |||
492 | }, | 496 | }, |
493 | .attach = com20020_attach, | 497 | .attach = com20020_attach, |
494 | .detach = com20020_detach, | 498 | .detach = com20020_detach, |
499 | .id_table = com20020_ids, | ||
495 | }; | 500 | }; |
496 | 501 | ||
497 | static int __init init_com20020_cs(void) | 502 | static int __init init_com20020_cs(void) |
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 0424865e8094..917adbbf0b5b 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -435,7 +435,9 @@ static void fmvj18x_config(dev_link_t *link) | |||
435 | pcmcia_get_status(handle, &status); | 435 | pcmcia_get_status(handle, &status); |
436 | if (status.CardState & CS_EVENT_3VCARD) | 436 | if (status.CardState & CS_EVENT_3VCARD) |
437 | link->conf.Vcc = 33; /* inserted in 3.3V slot */ | 437 | link->conf.Vcc = 33; /* inserted in 3.3V slot */ |
438 | } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) { | 438 | } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 |
439 | || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 | ||
440 | || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { | ||
439 | /* MultiFunction Card */ | 441 | /* MultiFunction Card */ |
440 | link->conf.ConfigBase = 0x800; | 442 | link->conf.ConfigBase = 0x800; |
441 | link->conf.ConfigIndex = 0x47; | 443 | link->conf.ConfigIndex = 0x47; |
@@ -764,6 +766,31 @@ static int fmvj18x_event(event_t event, int priority, | |||
764 | return 0; | 766 | return 0; |
765 | } /* fmvj18x_event */ | 767 | } /* fmvj18x_event */ |
766 | 768 | ||
769 | static struct pcmcia_device_id fmvj18x_ids[] = { | ||
770 | PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), | ||
771 | PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59), | ||
772 | PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922), | ||
773 | PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922), | ||
774 | PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db), | ||
775 | PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e), | ||
776 | PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2), | ||
777 | PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4), | ||
778 | PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0 ", 0x8cef4d3a, 0x075fc7b6), | ||
779 | PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0 ", 0x8cef4d3a, 0xbccf43e6), | ||
780 | PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666), | ||
781 | PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70), | ||
782 | PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a), | ||
783 | PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2), | ||
784 | PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304 ES", 0x2599f454), | ||
785 | PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da), | ||
786 | PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080), | ||
787 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), | ||
788 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a), | ||
789 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a), | ||
790 | PCMCIA_DEVICE_NULL, | ||
791 | }; | ||
792 | MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids); | ||
793 | |||
767 | static struct pcmcia_driver fmvj18x_cs_driver = { | 794 | static struct pcmcia_driver fmvj18x_cs_driver = { |
768 | .owner = THIS_MODULE, | 795 | .owner = THIS_MODULE, |
769 | .drv = { | 796 | .drv = { |
@@ -771,6 +798,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = { | |||
771 | }, | 798 | }, |
772 | .attach = fmvj18x_attach, | 799 | .attach = fmvj18x_attach, |
773 | .detach = fmvj18x_detach, | 800 | .detach = fmvj18x_detach, |
801 | .id_table = fmvj18x_ids, | ||
774 | }; | 802 | }; |
775 | 803 | ||
776 | static int __init init_fmvj18x_cs(void) | 804 | static int __init init_fmvj18x_cs(void) |
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index f0ff06e20410..cf6d073ea558 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
@@ -508,6 +508,13 @@ static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase) | |||
508 | return; | 508 | return; |
509 | } | 509 | } |
510 | 510 | ||
511 | static struct pcmcia_device_id ibmtr_ids[] = { | ||
512 | PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e), | ||
513 | PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47), | ||
514 | PCMCIA_DEVICE_NULL, | ||
515 | }; | ||
516 | MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids); | ||
517 | |||
511 | static struct pcmcia_driver ibmtr_cs_driver = { | 518 | static struct pcmcia_driver ibmtr_cs_driver = { |
512 | .owner = THIS_MODULE, | 519 | .owner = THIS_MODULE, |
513 | .drv = { | 520 | .drv = { |
@@ -515,6 +522,7 @@ static struct pcmcia_driver ibmtr_cs_driver = { | |||
515 | }, | 522 | }, |
516 | .attach = ibmtr_attach, | 523 | .attach = ibmtr_attach, |
517 | .detach = ibmtr_detach, | 524 | .detach = ibmtr_detach, |
525 | .id_table = ibmtr_ids, | ||
518 | }; | 526 | }; |
519 | 527 | ||
520 | static int __init init_ibmtr_cs(void) | 528 | static int __init init_ibmtr_cs(void) |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 4603807fcafb..b86e7253fbfc 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -1675,6 +1675,13 @@ static void set_multicast_list(struct net_device *dev) | |||
1675 | 1675 | ||
1676 | } /* set_multicast_list */ | 1676 | } /* set_multicast_list */ |
1677 | 1677 | ||
1678 | static struct pcmcia_device_id nmclan_ids[] = { | ||
1679 | PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941), | ||
1680 | PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet", 0x0ebf1d60, 0x00b2e941), | ||
1681 | PCMCIA_DEVICE_NULL, | ||
1682 | }; | ||
1683 | MODULE_DEVICE_TABLE(pcmcia, nmclan_ids); | ||
1684 | |||
1678 | static struct pcmcia_driver nmclan_cs_driver = { | 1685 | static struct pcmcia_driver nmclan_cs_driver = { |
1679 | .owner = THIS_MODULE, | 1686 | .owner = THIS_MODULE, |
1680 | .drv = { | 1687 | .drv = { |
@@ -1682,6 +1689,7 @@ static struct pcmcia_driver nmclan_cs_driver = { | |||
1682 | }, | 1689 | }, |
1683 | .attach = nmclan_attach, | 1690 | .attach = nmclan_attach, |
1684 | .detach = nmclan_detach, | 1691 | .detach = nmclan_detach, |
1692 | .id_table = nmclan_ids, | ||
1685 | }; | 1693 | }; |
1686 | 1694 | ||
1687 | static int __init init_nmclan_cs(void) | 1695 | static int __init init_nmclan_cs(void) |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index f3ea4a9f2bf1..855a45d062b1 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -1637,6 +1637,208 @@ failed: | |||
1637 | 1637 | ||
1638 | /*====================================================================*/ | 1638 | /*====================================================================*/ |
1639 | 1639 | ||
1640 | static struct pcmcia_device_id pcnet_ids[] = { | ||
1641 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021), | ||
1642 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a), | ||
1643 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15), | ||
1644 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341), | ||
1645 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab), | ||
1646 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101), | ||
1647 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab), | ||
1648 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet ", 0x578ba6e7, 0x02d92d1e), | ||
1649 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), | ||
1650 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), | ||
1651 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), | ||
1652 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), | ||
1653 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), | ||
1654 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), | ||
1655 | PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c), | ||
1656 | PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3), | ||
1657 | PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15), | ||
1658 | PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f), | ||
1659 | PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302), | ||
1660 | PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004), | ||
1661 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d), | ||
1662 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075), | ||
1663 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145), | ||
1664 | PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230), | ||
1665 | PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530), | ||
1666 | /* PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab), conflict with axnet_cs */ | ||
1667 | PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110), | ||
1668 | PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328), | ||
1669 | PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041), | ||
1670 | PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452), | ||
1671 | /* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), conflict with axnet_cs */ | ||
1672 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300), | ||
1673 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307), | ||
1674 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a), | ||
1675 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103), | ||
1676 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121), | ||
1677 | PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941), | ||
1678 | PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b), | ||
1679 | PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b), | ||
1680 | PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e), | ||
1681 | PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0), | ||
1682 | PCMCIA_DEVICE_PROD_ID123("EFA ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b), | ||
1683 | PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b), | ||
1684 | PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b), | ||
1685 | PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0), | ||
1686 | PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82), | ||
1687 | PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8), | ||
1688 | PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab), | ||
1689 | PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11), | ||
1690 | PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff), | ||
1691 | PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68), | ||
1692 | PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM", 0xbb7fbdd7, 0x5ba10d49), | ||
1693 | PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997), | ||
1694 | PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8), | ||
1695 | PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96), | ||
1696 | PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96), | ||
1697 | PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224), | ||
1698 | PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb), | ||
1699 | PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247), | ||
1700 | PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96), | ||
1701 | PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1), | ||
1702 | PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd), | ||
1703 | PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190), | ||
1704 | PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504), | ||
1705 | PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a), | ||
1706 | PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79), | ||
1707 | PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7), | ||
1708 | PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a), | ||
1709 | PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9), | ||
1710 | PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), | ||
1711 | PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), | ||
1712 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), | ||
1713 | PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), | ||
1714 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), | ||
1715 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), | ||
1716 | PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2), | ||
1717 | PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2), | ||
1718 | PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04), | ||
1719 | PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d), | ||
1720 | PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814), | ||
1721 | PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0), | ||
1722 | PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf), | ||
1723 | PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995), | ||
1724 | PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233), | ||
1725 | PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e), | ||
1726 | PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398), | ||
1727 | PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b), | ||
1728 | PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9), | ||
1729 | PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84), | ||
1730 | PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9), | ||
1731 | PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1), | ||
1732 | PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1), | ||
1733 | PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb), | ||
1734 | PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11), | ||
1735 | PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6), | ||
1736 | PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c), | ||
1737 | PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e), | ||
1738 | PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61), | ||
1739 | PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517), | ||
1740 | PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e), | ||
1741 | PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb), | ||
1742 | PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327), | ||
1743 | PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947), | ||
1744 | PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941), | ||
1745 | PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6), | ||
1746 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b), | ||
1747 | PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0), | ||
1748 | PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956), | ||
1749 | PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64), | ||
1750 | PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5), | ||
1751 | PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3), | ||
1752 | PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2), | ||
1753 | PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c), | ||
1754 | PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40), | ||
1755 | PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7), | ||
1756 | PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab), | ||
1757 | PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78), | ||
1758 | PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11), | ||
1759 | PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d), | ||
1760 | PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389), | ||
1761 | PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9), | ||
1762 | PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline ", 0x0733cc81, 0x5e07cfa0), | ||
1763 | PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737), | ||
1764 | PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922), | ||
1765 | PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0), | ||
1766 | PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578), | ||
1767 | PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307), | ||
1768 | PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4), | ||
1769 | PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8), | ||
1770 | PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3), | ||
1771 | PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c), | ||
1772 | PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6), | ||
1773 | PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472), | ||
1774 | PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7), | ||
1775 | PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9), | ||
1776 | PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8), | ||
1777 | PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76), | ||
1778 | PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e), | ||
1779 | PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875), | ||
1780 | PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f), | ||
1781 | PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1), | ||
1782 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b), | ||
1783 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941), | ||
1784 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b), | ||
1785 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8), | ||
1786 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0), | ||
1787 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c), | ||
1788 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8), | ||
1789 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb), | ||
1790 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4), | ||
1791 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7), | ||
1792 | PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941), | ||
1793 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641), | ||
1794 | PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), | ||
1795 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b), | ||
1796 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", " Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1), | ||
1797 | PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80), | ||
1798 | PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), | ||
1799 | PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), | ||
1800 | PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), | ||
1801 | PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), | ||
1802 | PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), | ||
1803 | PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), | ||
1804 | PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388), | ||
1805 | PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c), | ||
1806 | PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941), | ||
1807 | PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265), | ||
1808 | PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e), | ||
1809 | PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8), | ||
1810 | PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa), | ||
1811 | PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f), | ||
1812 | PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a), | ||
1813 | PCMCIA_DEVICE_PROD_ID13("Hypertec", "EP401", 0x8787bec7, 0xf6e4a31e), | ||
1814 | PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0), | ||
1815 | PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e), | ||
1816 | PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89), | ||
1817 | PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360), | ||
1818 | PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de), | ||
1819 | PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f), | ||
1820 | PCMCIA_DEVICE_PROD_ID1("IC-CARD", 0x60cb09a6), | ||
1821 | PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a), | ||
1822 | PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078), | ||
1823 | /* too generic! */ | ||
1824 | /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */ | ||
1825 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), | ||
1826 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), | ||
1827 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), | ||
1828 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"), | ||
1829 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), | ||
1830 | PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), | ||
1831 | PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), | ||
1832 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"), | ||
1833 | PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "LA-PCM.cis"), | ||
1834 | PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"), | ||
1835 | PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"), | ||
1836 | PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), | ||
1837 | PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"), | ||
1838 | PCMCIA_DEVICE_NULL | ||
1839 | }; | ||
1840 | MODULE_DEVICE_TABLE(pcmcia, pcnet_ids); | ||
1841 | |||
1640 | static struct pcmcia_driver pcnet_driver = { | 1842 | static struct pcmcia_driver pcnet_driver = { |
1641 | .drv = { | 1843 | .drv = { |
1642 | .name = "pcnet_cs", | 1844 | .name = "pcnet_cs", |
@@ -1644,6 +1846,7 @@ static struct pcmcia_driver pcnet_driver = { | |||
1644 | .attach = pcnet_attach, | 1846 | .attach = pcnet_attach, |
1645 | .detach = pcnet_detach, | 1847 | .detach = pcnet_detach, |
1646 | .owner = THIS_MODULE, | 1848 | .owner = THIS_MODULE, |
1849 | .id_table = pcnet_ids, | ||
1647 | }; | 1850 | }; |
1648 | 1851 | ||
1649 | static int __init init_pcnet_cs(void) | 1852 | static int __init init_pcnet_cs(void) |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 8a5e52c40e46..bc01c88c6709 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -2327,6 +2327,38 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) | |||
2327 | return rc; | 2327 | return rc; |
2328 | } | 2328 | } |
2329 | 2329 | ||
2330 | static struct pcmcia_device_id smc91c92_ids[] = { | ||
2331 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501), | ||
2332 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a), | ||
2333 | PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), | ||
2334 | PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63), | ||
2335 | PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef), | ||
2336 | PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef), | ||
2337 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), | ||
2338 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), | ||
2339 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), | ||
2340 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), | ||
2341 | PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x016c, 0x0020), | ||
2342 | PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0023), | ||
2343 | PCMCIA_DEVICE_PROD_ID123("BASICS by New Media Corporation", "Ethernet", "SMC91C94", 0x23c78a9d, 0x00b2e941, 0xcef397fb), | ||
2344 | PCMCIA_DEVICE_PROD_ID12("ARGOSY", "Fast Ethernet PCCard", 0x78f308dc, 0xdcea68bc), | ||
2345 | PCMCIA_DEVICE_PROD_ID12("dit Co., Ltd.", "PC Card-10/100BTX", 0xe59365c8, 0x6a2161d1), | ||
2346 | PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L100C", 0x6a26d1cf, 0xc16ce9c5), | ||
2347 | PCMCIA_DEVICE_PROD_ID12("Farallon", "Farallon Enet", 0x58d93fc4, 0x244734e9), | ||
2348 | PCMCIA_DEVICE_PROD_ID12("Megahertz", "CC10BT/2", 0x33234748, 0x3c95b953), | ||
2349 | PCMCIA_DEVICE_PROD_ID12("MELCO/SMC", "LPC-TX", 0xa2cd8e6d, 0x42da662a), | ||
2350 | PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), | ||
2351 | PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), | ||
2352 | PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast Ethernet PCCard", 0x281f1c5d, 0xdcea68bc), | ||
2353 | PCMCIA_DEVICE_PROD_ID12("Psion", "10Mb Ethernet", 0x4ef00b21, 0x844be9e9), | ||
2354 | PCMCIA_DEVICE_PROD_ID12("SMC", "EtherEZ Ethernet 8020", 0xc4f8b18b, 0x4a0eeb2d), | ||
2355 | /* These conflict with other cards! */ | ||
2356 | /* PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0100), */ | ||
2357 | /* PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), */ | ||
2358 | PCMCIA_DEVICE_NULL, | ||
2359 | }; | ||
2360 | MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids); | ||
2361 | |||
2330 | static struct pcmcia_driver smc91c92_cs_driver = { | 2362 | static struct pcmcia_driver smc91c92_cs_driver = { |
2331 | .owner = THIS_MODULE, | 2363 | .owner = THIS_MODULE, |
2332 | .drv = { | 2364 | .drv = { |
@@ -2334,6 +2366,7 @@ static struct pcmcia_driver smc91c92_cs_driver = { | |||
2334 | }, | 2366 | }, |
2335 | .attach = smc91c92_attach, | 2367 | .attach = smc91c92_attach, |
2336 | .detach = smc91c92_detach, | 2368 | .detach = smc91c92_detach, |
2369 | .id_table = smc91c92_ids, | ||
2337 | }; | 2370 | }; |
2338 | 2371 | ||
2339 | static int __init init_smc91c92_cs(void) | 2372 | static int __init init_smc91c92_cs(void) |
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 58177d67ea12..0cd225e1595c 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -1983,6 +1983,33 @@ do_stop(struct net_device *dev) | |||
1983 | return 0; | 1983 | return 0; |
1984 | } | 1984 | } |
1985 | 1985 | ||
1986 | static struct pcmcia_device_id xirc2ps_ids[] = { | ||
1987 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a), | ||
1988 | PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a), | ||
1989 | PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), | ||
1990 | PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), | ||
1991 | PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), | ||
1992 | PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), | ||
1993 | PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), | ||
1994 | PCMCIA_PFC_DEVICE_PROD_ID12(0, "Xircom", "CreditCard Ethernet", 0x2e3ee845, 0xc0e778c2), | ||
1995 | PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x010a), | ||
1996 | PCMCIA_DEVICE_PROD_ID13("Toshiba Information Systems", "TPCENET", 0x1b3b94fe, 0xf381c1a2), | ||
1997 | PCMCIA_DEVICE_PROD_ID13("Xircom", "CE3-10/100", 0x2e3ee845, 0x0ec0ac37), | ||
1998 | PCMCIA_DEVICE_PROD_ID13("Xircom", "PS-CE2-10", 0x2e3ee845, 0x947d9073), | ||
1999 | PCMCIA_DEVICE_PROD_ID13("Xircom", "R2E-100BTX", 0x2e3ee845, 0x2464a6e3), | ||
2000 | PCMCIA_DEVICE_PROD_ID13("Xircom", "RE-10", 0x2e3ee845, 0x3e08d609), | ||
2001 | PCMCIA_DEVICE_PROD_ID13("Xircom", "XE2000", 0x2e3ee845, 0xf7188e46), | ||
2002 | PCMCIA_DEVICE_PROD_ID12("Compaq", "Ethernet LAN Card", 0x54f7c49c, 0x9fd2f0a2), | ||
2003 | PCMCIA_DEVICE_PROD_ID12("Compaq", "Netelligent 10/100 PC Card", 0x54f7c49c, 0xefe96769), | ||
2004 | PCMCIA_DEVICE_PROD_ID12("Intel", "EtherExpress(TM) PRO/100 PC Card Mobile Adapter16", 0x816cc815, 0x174397db), | ||
2005 | PCMCIA_DEVICE_PROD_ID12("Toshiba", "10/100 Ethernet PC Card", 0x44a09d9c, 0xb44deecf), | ||
2006 | /* also matches CFE-10 cards! */ | ||
2007 | /* PCMCIA_DEVICE_MANF_CARD(0x0105, 0x010a), */ | ||
2008 | PCMCIA_DEVICE_NULL, | ||
2009 | }; | ||
2010 | MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids); | ||
2011 | |||
2012 | |||
1986 | static struct pcmcia_driver xirc2ps_cs_driver = { | 2013 | static struct pcmcia_driver xirc2ps_cs_driver = { |
1987 | .owner = THIS_MODULE, | 2014 | .owner = THIS_MODULE, |
1988 | .drv = { | 2015 | .drv = { |
@@ -1990,6 +2017,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = { | |||
1990 | }, | 2017 | }, |
1991 | .attach = xirc2ps_attach, | 2018 | .attach = xirc2ps_attach, |
1992 | .detach = xirc2ps_detach, | 2019 | .detach = xirc2ps_detach, |
2020 | .id_table = xirc2ps_ids, | ||
1993 | }; | 2021 | }; |
1994 | 2022 | ||
1995 | static int __init | 2023 | static int __init |
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index fbf53af6cda4..f10a9523034a 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -559,6 +559,15 @@ static int airo_event(event_t event, int priority, | |||
559 | return 0; | 559 | return 0; |
560 | } /* airo_event */ | 560 | } /* airo_event */ |
561 | 561 | ||
562 | static struct pcmcia_device_id airo_ids[] = { | ||
563 | PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), | ||
564 | PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005), | ||
565 | PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007), | ||
566 | PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007), | ||
567 | PCMCIA_DEVICE_NULL, | ||
568 | }; | ||
569 | MODULE_DEVICE_TABLE(pcmcia, airo_ids); | ||
570 | |||
562 | static struct pcmcia_driver airo_driver = { | 571 | static struct pcmcia_driver airo_driver = { |
563 | .owner = THIS_MODULE, | 572 | .owner = THIS_MODULE, |
564 | .drv = { | 573 | .drv = { |
@@ -566,6 +575,7 @@ static struct pcmcia_driver airo_driver = { | |||
566 | }, | 575 | }, |
567 | .attach = airo_attach, | 576 | .attach = airo_attach, |
568 | .detach = airo_detach, | 577 | .detach = airo_detach, |
578 | .id_table = airo_ids, | ||
569 | }; | 579 | }; |
570 | 580 | ||
571 | static int airo_cs_init(void) | 581 | static int airo_cs_init(void) |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index a4ed28d9c783..86379d4998ac 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -646,6 +646,27 @@ static int atmel_event(event_t event, int priority, | |||
646 | } /* atmel_event */ | 646 | } /* atmel_event */ |
647 | 647 | ||
648 | /*====================================================================*/ | 648 | /*====================================================================*/ |
649 | static struct pcmcia_device_id atmel_ids[] = { | ||
650 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0620), | ||
651 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0696), | ||
652 | PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3302), | ||
653 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0007), | ||
654 | PCMCIA_DEVICE_PROD_ID12("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9), | ||
655 | PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f), | ||
656 | PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504", 0xabda4164, 0x5040670a), | ||
657 | PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f), | ||
658 | PCMCIA_DEVICE_PROD_ID12("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5), | ||
659 | PCMCIA_DEVICE_PROD_ID12("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b), | ||
660 | PCMCIA_DEVICE_PROD_ID12("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6), | ||
661 | PCMCIA_DEVICE_PROD_ID12("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68), | ||
662 | PCMCIA_DEVICE_PROD_ID12("SMC", "2632W", 0xc4f8b18b, 0x30f38774), | ||
663 | PCMCIA_DEVICE_PROD_ID12("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377), | ||
664 | PCMCIA_DEVICE_PROD_ID12("Wireless", "PC", 0xa407ecdd, 0x556e4d7e), | ||
665 | PCMCIA_DEVICE_PROD_ID12("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4), | ||
666 | PCMCIA_DEVICE_NULL | ||
667 | }; | ||
668 | MODULE_DEVICE_TABLE(pcmcia, atmel_ids); | ||
669 | |||
649 | static struct pcmcia_driver atmel_driver = { | 670 | static struct pcmcia_driver atmel_driver = { |
650 | .owner = THIS_MODULE, | 671 | .owner = THIS_MODULE, |
651 | .drv = { | 672 | .drv = { |
@@ -653,6 +674,7 @@ static struct pcmcia_driver atmel_driver = { | |||
653 | }, | 674 | }, |
654 | .attach = atmel_attach, | 675 | .attach = atmel_attach, |
655 | .detach = atmel_detach, | 676 | .detach = atmel_detach, |
677 | .id_table = atmel_ids, | ||
656 | }; | 678 | }; |
657 | 679 | ||
658 | static int atmel_cs_init(void) | 680 | static int atmel_cs_init(void) |
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 382241e7edbb..e12bd75b2694 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c | |||
@@ -1668,6 +1668,12 @@ static int netwave_close(struct net_device *dev) { | |||
1668 | return 0; | 1668 | return 0; |
1669 | } | 1669 | } |
1670 | 1670 | ||
1671 | static struct pcmcia_device_id netwave_ids[] = { | ||
1672 | PCMCIA_DEVICE_PROD_ID12("Xircom", "CreditCard Netwave", 0x2e3ee845, 0x54e28a28), | ||
1673 | PCMCIA_DEVICE_NULL, | ||
1674 | }; | ||
1675 | MODULE_DEVICE_TABLE(pcmcia, netwave_ids); | ||
1676 | |||
1671 | static struct pcmcia_driver netwave_driver = { | 1677 | static struct pcmcia_driver netwave_driver = { |
1672 | .owner = THIS_MODULE, | 1678 | .owner = THIS_MODULE, |
1673 | .drv = { | 1679 | .drv = { |
@@ -1675,6 +1681,7 @@ static struct pcmcia_driver netwave_driver = { | |||
1675 | }, | 1681 | }, |
1676 | .attach = netwave_attach, | 1682 | .attach = netwave_attach, |
1677 | .detach = netwave_detach, | 1683 | .detach = netwave_detach, |
1684 | .id_table = netwave_ids, | ||
1678 | }; | 1685 | }; |
1679 | 1686 | ||
1680 | static int __init init_netwave_cs(void) | 1687 | static int __init init_netwave_cs(void) |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 74a8227256aa..597c4586d049 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -608,6 +608,56 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | |||
608 | " (David Gibson <hermes@gibson.dropbear.id.au>, " | 608 | " (David Gibson <hermes@gibson.dropbear.id.au>, " |
609 | "Pavel Roskin <proski@gnu.org>, et al)"; | 609 | "Pavel Roskin <proski@gnu.org>, et al)"; |
610 | 610 | ||
611 | static struct pcmcia_device_id orinoco_cs_ids[] = { | ||
612 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), | ||
613 | PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), | ||
614 | PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), | ||
615 | PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), | ||
616 | PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), | ||
617 | PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), | ||
618 | PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), | ||
619 | PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), | ||
620 | PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), | ||
621 | PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), | ||
622 | PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), | ||
623 | PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), | ||
624 | PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), | ||
625 | PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), | ||
626 | PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), | ||
627 | PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), | ||
628 | PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), | ||
629 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), | ||
630 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), | ||
631 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), | ||
632 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), | ||
633 | PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), | ||
634 | PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), | ||
635 | PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), | ||
636 | PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), | ||
637 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), | ||
638 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), | ||
639 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), | ||
640 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), | ||
641 | PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), | ||
642 | PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), | ||
643 | PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), | ||
644 | PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), | ||
645 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), | ||
646 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), | ||
647 | PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), | ||
648 | PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), | ||
649 | PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01), | ||
650 | PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), | ||
651 | PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1), | ||
652 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), | ||
653 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), | ||
654 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), | ||
655 | PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), | ||
656 | PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6), | ||
657 | PCMCIA_DEVICE_NULL, | ||
658 | }; | ||
659 | MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); | ||
660 | |||
611 | static struct pcmcia_driver orinoco_driver = { | 661 | static struct pcmcia_driver orinoco_driver = { |
612 | .owner = THIS_MODULE, | 662 | .owner = THIS_MODULE, |
613 | .drv = { | 663 | .drv = { |
@@ -615,6 +665,7 @@ static struct pcmcia_driver orinoco_driver = { | |||
615 | }, | 665 | }, |
616 | .attach = orinoco_cs_attach, | 666 | .attach = orinoco_cs_attach, |
617 | .detach = orinoco_cs_detach, | 667 | .detach = orinoco_cs_detach, |
668 | .id_table = orinoco_cs_ids, | ||
618 | }; | 669 | }; |
619 | 670 | ||
620 | static int __init | 671 | static int __init |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 6e5bda56b8f8..31652af52eac 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -2904,6 +2904,12 @@ static int write_int(struct file *file, const char __user *buffer, unsigned long | |||
2904 | } | 2904 | } |
2905 | #endif | 2905 | #endif |
2906 | 2906 | ||
2907 | static struct pcmcia_device_id ray_ids[] = { | ||
2908 | PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), | ||
2909 | PCMCIA_DEVICE_NULL, | ||
2910 | }; | ||
2911 | MODULE_DEVICE_TABLE(pcmcia, ray_ids); | ||
2912 | |||
2907 | static struct pcmcia_driver ray_driver = { | 2913 | static struct pcmcia_driver ray_driver = { |
2908 | .owner = THIS_MODULE, | 2914 | .owner = THIS_MODULE, |
2909 | .drv = { | 2915 | .drv = { |
@@ -2911,6 +2917,7 @@ static struct pcmcia_driver ray_driver = { | |||
2911 | }, | 2917 | }, |
2912 | .attach = ray_attach, | 2918 | .attach = ray_attach, |
2913 | .detach = ray_detach, | 2919 | .detach = ray_detach, |
2920 | .id_table = ray_ids, | ||
2914 | }; | 2921 | }; |
2915 | 2922 | ||
2916 | static int __init init_ray_cs(void) | 2923 | static int __init init_ray_cs(void) |
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index ec8329788e49..89532fd92941 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -4889,6 +4889,15 @@ wavelan_event(event_t event, /* The event received */ | |||
4889 | return 0; | 4889 | return 0; |
4890 | } | 4890 | } |
4891 | 4891 | ||
4892 | static struct pcmcia_device_id wavelan_ids[] = { | ||
4893 | PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), | ||
4894 | PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), | ||
4895 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/PCMCIA", 0x23eb9949, 0x1bc50975), | ||
4896 | PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/PCMCIA", 0x24358cd4, 0x1bc50975), | ||
4897 | PCMCIA_DEVICE_NULL, | ||
4898 | }; | ||
4899 | MODULE_DEVICE_TABLE(pcmcia, wavelan_ids); | ||
4900 | |||
4892 | static struct pcmcia_driver wavelan_driver = { | 4901 | static struct pcmcia_driver wavelan_driver = { |
4893 | .owner = THIS_MODULE, | 4902 | .owner = THIS_MODULE, |
4894 | .drv = { | 4903 | .drv = { |
@@ -4896,6 +4905,7 @@ static struct pcmcia_driver wavelan_driver = { | |||
4896 | }, | 4905 | }, |
4897 | .attach = wavelan_attach, | 4906 | .attach = wavelan_attach, |
4898 | .detach = wavelan_detach, | 4907 | .detach = wavelan_detach, |
4908 | .id_table = wavelan_ids, | ||
4899 | }; | 4909 | }; |
4900 | 4910 | ||
4901 | static int __init | 4911 | static int __init |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 1433e5aaf1b4..e3a900482d92 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -2239,6 +2239,12 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args) | |||
2239 | return 0; | 2239 | return 0; |
2240 | } | 2240 | } |
2241 | 2241 | ||
2242 | static struct pcmcia_device_id wl3501_ids[] = { | ||
2243 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), | ||
2244 | PCMCIA_DEVICE_NULL | ||
2245 | }; | ||
2246 | MODULE_DEVICE_TABLE(pcmcia, wl3501_ids); | ||
2247 | |||
2242 | static struct pcmcia_driver wl3501_driver = { | 2248 | static struct pcmcia_driver wl3501_driver = { |
2243 | .owner = THIS_MODULE, | 2249 | .owner = THIS_MODULE, |
2244 | .drv = { | 2250 | .drv = { |
@@ -2246,6 +2252,7 @@ static struct pcmcia_driver wl3501_driver = { | |||
2246 | }, | 2252 | }, |
2247 | .attach = wl3501_attach, | 2253 | .attach = wl3501_attach, |
2248 | .detach = wl3501_detach, | 2254 | .detach = wl3501_detach, |
2255 | .id_table = wl3501_ids, | ||
2249 | }; | 2256 | }; |
2250 | 2257 | ||
2251 | static int __init wl3501_init_module(void) | 2258 | static int __init wl3501_init_module(void) |
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index a3fa8185af2a..ff45662c4f7c 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c | |||
@@ -373,6 +373,13 @@ int parport_event(event_t event, int priority, | |||
373 | return 0; | 373 | return 0; |
374 | } /* parport_event */ | 374 | } /* parport_event */ |
375 | 375 | ||
376 | static struct pcmcia_device_id parport_ids[] = { | ||
377 | PCMCIA_DEVICE_FUNC_ID(3), | ||
378 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003), | ||
379 | PCMCIA_DEVICE_NULL | ||
380 | }; | ||
381 | MODULE_DEVICE_TABLE(pcmcia, parport_ids); | ||
382 | |||
376 | static struct pcmcia_driver parport_cs_driver = { | 383 | static struct pcmcia_driver parport_cs_driver = { |
377 | .owner = THIS_MODULE, | 384 | .owner = THIS_MODULE, |
378 | .drv = { | 385 | .drv = { |
@@ -380,6 +387,8 @@ static struct pcmcia_driver parport_cs_driver = { | |||
380 | }, | 387 | }, |
381 | .attach = parport_attach, | 388 | .attach = parport_attach, |
382 | .detach = parport_detach, | 389 | .detach = parport_detach, |
390 | .id_table = parport_ids, | ||
391 | |||
383 | }; | 392 | }; |
384 | 393 | ||
385 | static int __init init_parport_cs(void) | 394 | static int __init init_parport_cs(void) |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 14e4124e1523..52ea34594363 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -14,8 +14,8 @@ config PCCARD | |||
14 | Say Y here if you want to attach PCMCIA- or PC-cards to your Linux | 14 | Say Y here if you want to attach PCMCIA- or PC-cards to your Linux |
15 | computer. These are credit-card size devices such as network cards, | 15 | computer. These are credit-card size devices such as network cards, |
16 | modems or hard drives often used with laptops computers. There are | 16 | modems or hard drives often used with laptops computers. There are |
17 | actually two varieties of these cards: the older 16 bit PCMCIA cards | 17 | actually two varieties of these cards: 16 bit PCMCIA and 32 bit |
18 | and the newer 32 bit CardBus cards. | 18 | CardBus cards. |
19 | 19 | ||
20 | To compile this driver as modules, choose M here: the | 20 | To compile this driver as modules, choose M here: the |
21 | module will be called pcmcia_core. | 21 | module will be called pcmcia_core. |
@@ -42,22 +42,51 @@ config PCMCIA_DEBUG | |||
42 | 42 | ||
43 | config PCMCIA | 43 | config PCMCIA |
44 | tristate "16-bit PCMCIA support" | 44 | tristate "16-bit PCMCIA support" |
45 | select CRC32 | ||
45 | default y | 46 | default y |
46 | ---help--- | 47 | ---help--- |
47 | This option enables support for 16-bit PCMCIA cards. Most older | 48 | This option enables support for 16-bit PCMCIA cards. Most older |
48 | PC-cards are such 16-bit PCMCIA cards, so unless you know you're | 49 | PC-cards are such 16-bit PCMCIA cards, so unless you know you're |
49 | only using 32-bit CardBus cards, say Y or M here. | 50 | only using 32-bit CardBus cards, say Y or M here. |
50 | 51 | ||
51 | To use 16-bit PCMCIA cards, you will need supporting software from | 52 | To use 16-bit PCMCIA cards, you will need supporting software in |
52 | David Hinds' pcmcia-cs package (see the file <file:Documentation/Changes> | 53 | most cases. (see the file <file:Documentation/Changes> for |
53 | for location). Please also read the PCMCIA-HOWTO, available from | 54 | location and details). |
54 | <http://www.tldp.org/docs.html#howto>. | ||
55 | 55 | ||
56 | To compile this driver as modules, choose M here: the | 56 | To compile this driver as modules, choose M here: the |
57 | module will be called pcmcia. | 57 | module will be called pcmcia. |
58 | 58 | ||
59 | If unsure, say Y. | 59 | If unsure, say Y. |
60 | 60 | ||
61 | config PCMCIA_LOAD_CIS | ||
62 | bool "Load CIS updates from userspace (EXPERIMENTAL)" | ||
63 | depends on PCMCIA && EXPERIMENTAL | ||
64 | select FW_LOADER | ||
65 | default y | ||
66 | help | ||
67 | Some PCMCIA cards require an updated Card Information Structure (CIS) | ||
68 | to be loaded from userspace to work correctly. If you say Y here, | ||
69 | and your userspace is arranged correctly, this will be loaded | ||
70 | automatically using the in-kernel firmware loader and the hotplug | ||
71 | subsystem, instead of relying on cardmgr from pcmcia-cs to do so. | ||
72 | |||
73 | If unsure, say Y. | ||
74 | |||
75 | config PCMCIA_IOCTL | ||
76 | bool | ||
77 | depends on PCMCIA | ||
78 | default y | ||
79 | help | ||
80 | If you say Y here, the deprecated ioctl interface to the PCMCIA | ||
81 | subsystem will be built. It is needed by cardmgr and cardctl | ||
82 | (pcmcia-cs) to function properly. | ||
83 | |||
84 | If you do not use the new pcmciautils package, and have a | ||
85 | yenta, Cirrus PD6729, i82092, i82365 or tcic compatible bridge, | ||
86 | you need to say Y here to be able to use 16-bit PCMCIA cards. | ||
87 | |||
88 | If unsure, say Y. | ||
89 | |||
61 | config CARDBUS | 90 | config CARDBUS |
62 | bool "32-bit CardBus support" | 91 | bool "32-bit CardBus support" |
63 | depends on PCI | 92 | depends on PCI |
@@ -77,8 +106,6 @@ comment "PC-card bridges" | |||
77 | 106 | ||
78 | config YENTA | 107 | config YENTA |
79 | tristate "CardBus yenta-compatible bridge support" | 108 | tristate "CardBus yenta-compatible bridge support" |
80 | depends on PCI | ||
81 | #fixme: remove dependendcy on CARDBUS | ||
82 | depends on CARDBUS | 109 | depends on CARDBUS |
83 | select PCCARD_NONSTATIC | 110 | select PCCARD_NONSTATIC |
84 | ---help--- | 111 | ---help--- |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 50c29361bc5f..ef694c74dfb7 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -10,7 +10,8 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o | |||
10 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o | 10 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o |
11 | obj-$(CONFIG_PCCARD) += pcmcia_core.o | 11 | obj-$(CONFIG_PCCARD) += pcmcia_core.o |
12 | 12 | ||
13 | pcmcia-y += ds.o pcmcia_compat.o | 13 | pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o |
14 | pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o | ||
14 | obj-$(CONFIG_PCMCIA) += pcmcia.o | 15 | obj-$(CONFIG_PCMCIA) += pcmcia.o |
15 | 16 | ||
16 | obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o | 17 | obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o |
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index e29a6ddf2fd7..dd7651ff5b43 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -89,8 +89,10 @@ static void __iomem * | |||
89 | set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) | 89 | set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) |
90 | { | 90 | { |
91 | pccard_mem_map *mem = &s->cis_mem; | 91 | pccard_mem_map *mem = &s->cis_mem; |
92 | int ret; | ||
93 | |||
92 | if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) { | 94 | if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) { |
93 | mem->res = find_mem_region(0, s->map_size, s->map_size, 0, s); | 95 | mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s); |
94 | if (mem->res == NULL) { | 96 | if (mem->res == NULL) { |
95 | printk(KERN_NOTICE "cs: unable to map card memory!\n"); | 97 | printk(KERN_NOTICE "cs: unable to map card memory!\n"); |
96 | return NULL; | 98 | return NULL; |
@@ -99,7 +101,12 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag | |||
99 | } | 101 | } |
100 | mem->card_start = card_offset; | 102 | mem->card_start = card_offset; |
101 | mem->flags = flags; | 103 | mem->flags = flags; |
102 | s->ops->set_mem_map(s, mem); | 104 | ret = s->ops->set_mem_map(s, mem); |
105 | if (ret) { | ||
106 | iounmap(s->cis_virt); | ||
107 | return NULL; | ||
108 | } | ||
109 | |||
103 | if (s->features & SS_CAP_STATIC_MAP) { | 110 | if (s->features & SS_CAP_STATIC_MAP) { |
104 | if (s->cis_virt) | 111 | if (s->cis_virt) |
105 | iounmap(s->cis_virt); | 112 | iounmap(s->cis_virt); |
@@ -119,13 +126,13 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag | |||
119 | #define IS_ATTR 1 | 126 | #define IS_ATTR 1 |
120 | #define IS_INDIRECT 8 | 127 | #define IS_INDIRECT 8 |
121 | 128 | ||
122 | int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | 129 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, |
123 | u_int len, void *ptr) | 130 | u_int len, void *ptr) |
124 | { | 131 | { |
125 | void __iomem *sys, *end; | 132 | void __iomem *sys, *end; |
126 | unsigned char *buf = ptr; | 133 | unsigned char *buf = ptr; |
127 | 134 | ||
128 | cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len); | 135 | cs_dbg(s, 3, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); |
129 | 136 | ||
130 | if (attr & IS_INDIRECT) { | 137 | if (attr & IS_INDIRECT) { |
131 | /* Indirect accesses use a bunch of special registers at fixed | 138 | /* Indirect accesses use a bunch of special registers at fixed |
@@ -182,14 +189,16 @@ int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
182 | *(u_char *)(ptr+2), *(u_char *)(ptr+3)); | 189 | *(u_char *)(ptr+2), *(u_char *)(ptr+3)); |
183 | return 0; | 190 | return 0; |
184 | } | 191 | } |
192 | EXPORT_SYMBOL(pcmcia_read_cis_mem); | ||
193 | |||
185 | 194 | ||
186 | void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | 195 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, |
187 | u_int len, void *ptr) | 196 | u_int len, void *ptr) |
188 | { | 197 | { |
189 | void __iomem *sys, *end; | 198 | void __iomem *sys, *end; |
190 | unsigned char *buf = ptr; | 199 | unsigned char *buf = ptr; |
191 | 200 | ||
192 | cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len); | 201 | cs_dbg(s, 3, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); |
193 | 202 | ||
194 | if (attr & IS_INDIRECT) { | 203 | if (attr & IS_INDIRECT) { |
195 | /* Indirect accesses use a bunch of special registers at fixed | 204 | /* Indirect accesses use a bunch of special registers at fixed |
@@ -239,6 +248,8 @@ void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, | |||
239 | } | 248 | } |
240 | } | 249 | } |
241 | } | 250 | } |
251 | EXPORT_SYMBOL(pcmcia_write_cis_mem); | ||
252 | |||
242 | 253 | ||
243 | /*====================================================================== | 254 | /*====================================================================== |
244 | 255 | ||
@@ -274,7 +285,7 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, | |||
274 | ret = read_cb_mem(s, attr, addr, len, ptr); | 285 | ret = read_cb_mem(s, attr, addr, len, ptr); |
275 | else | 286 | else |
276 | #endif | 287 | #endif |
277 | ret = read_cis_mem(s, attr, addr, len, ptr); | 288 | ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); |
278 | 289 | ||
279 | if (ret == 0) { | 290 | if (ret == 0) { |
280 | /* Copy data into the cache */ | 291 | /* Copy data into the cache */ |
@@ -348,7 +359,7 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
348 | read_cb_mem(s, cis->attr, cis->addr, len, buf); | 359 | read_cb_mem(s, cis->attr, cis->addr, len, buf); |
349 | else | 360 | else |
350 | #endif | 361 | #endif |
351 | read_cis_mem(s, cis->attr, cis->addr, len, buf); | 362 | pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); |
352 | 363 | ||
353 | if (memcmp(buf, cis->cache, len) != 0) { | 364 | if (memcmp(buf, cis->cache, len) != 0) { |
354 | kfree(buf); | 365 | kfree(buf); |
@@ -381,6 +392,7 @@ int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) | |||
381 | memcpy(s->fake_cis, cis->Data, cis->Length); | 392 | memcpy(s->fake_cis, cis->Data, cis->Length); |
382 | return CS_SUCCESS; | 393 | return CS_SUCCESS; |
383 | } | 394 | } |
395 | EXPORT_SYMBOL(pcmcia_replace_cis); | ||
384 | 396 | ||
385 | /*====================================================================== | 397 | /*====================================================================== |
386 | 398 | ||
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 48e4f04530d8..e82859d3227a 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -43,36 +43,11 @@ | |||
43 | #include <pcmcia/ds.h> | 43 | #include <pcmcia/ds.h> |
44 | #include "cs_internal.h" | 44 | #include "cs_internal.h" |
45 | 45 | ||
46 | #ifdef CONFIG_PCI | ||
47 | #define PCI_OPT " [pci]" | ||
48 | #else | ||
49 | #define PCI_OPT "" | ||
50 | #endif | ||
51 | #ifdef CONFIG_CARDBUS | ||
52 | #define CB_OPT " [cardbus]" | ||
53 | #else | ||
54 | #define CB_OPT "" | ||
55 | #endif | ||
56 | #ifdef CONFIG_PM | ||
57 | #define PM_OPT " [pm]" | ||
58 | #else | ||
59 | #define PM_OPT "" | ||
60 | #endif | ||
61 | #if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && !defined(CONFIG_PM) | ||
62 | #define OPTIONS " none" | ||
63 | #else | ||
64 | #define OPTIONS PCI_OPT CB_OPT PM_OPT | ||
65 | #endif | ||
66 | |||
67 | static const char *release = "Linux Kernel Card Services"; | ||
68 | static const char *options = "options: " OPTIONS; | ||
69 | |||
70 | /*====================================================================*/ | ||
71 | 46 | ||
72 | /* Module parameters */ | 47 | /* Module parameters */ |
73 | 48 | ||
74 | MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); | 49 | MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); |
75 | MODULE_DESCRIPTION("Linux Kernel Card Services\noptions:" OPTIONS); | 50 | MODULE_DESCRIPTION("Linux Kernel Card Services"); |
76 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
77 | 52 | ||
78 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) | 53 | #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) |
@@ -89,9 +64,6 @@ INT_MODULE_PARM(unreset_limit, 30); /* unreset_check's */ | |||
89 | /* Access speed for attribute memory windows */ | 64 | /* Access speed for attribute memory windows */ |
90 | INT_MODULE_PARM(cis_speed, 300); /* ns */ | 65 | INT_MODULE_PARM(cis_speed, 300); /* ns */ |
91 | 66 | ||
92 | /* Access speed for IO windows */ | ||
93 | INT_MODULE_PARM(io_speed, 0); /* ns */ | ||
94 | |||
95 | #ifdef DEBUG | 67 | #ifdef DEBUG |
96 | static int pc_debug; | 68 | static int pc_debug; |
97 | 69 | ||
@@ -103,34 +75,26 @@ int cs_debug_level(int level) | |||
103 | } | 75 | } |
104 | #endif | 76 | #endif |
105 | 77 | ||
106 | /*====================================================================*/ | ||
107 | 78 | ||
108 | socket_state_t dead_socket = { | 79 | socket_state_t dead_socket = { |
109 | .csc_mask = SS_DETECT, | 80 | .csc_mask = SS_DETECT, |
110 | }; | 81 | }; |
82 | EXPORT_SYMBOL(dead_socket); | ||
111 | 83 | ||
112 | 84 | ||
113 | /* List of all sockets, protected by a rwsem */ | 85 | /* List of all sockets, protected by a rwsem */ |
114 | LIST_HEAD(pcmcia_socket_list); | 86 | LIST_HEAD(pcmcia_socket_list); |
115 | DECLARE_RWSEM(pcmcia_socket_list_rwsem); | ||
116 | EXPORT_SYMBOL(pcmcia_socket_list); | 87 | EXPORT_SYMBOL(pcmcia_socket_list); |
117 | EXPORT_SYMBOL(pcmcia_socket_list_rwsem); | ||
118 | |||
119 | 88 | ||
120 | #ifdef CONFIG_PCMCIA_PROBE | 89 | DECLARE_RWSEM(pcmcia_socket_list_rwsem); |
121 | /* mask ofIRQs already reserved by other cards, we should avoid using them */ | 90 | EXPORT_SYMBOL(pcmcia_socket_list_rwsem); |
122 | static u8 pcmcia_used_irq[NR_IRQS]; | ||
123 | #endif | ||
124 | 91 | ||
125 | /*==================================================================== | ||
126 | |||
127 | Low-level PC Card interface drivers need to register with Card | ||
128 | Services using these calls. | ||
129 | |||
130 | ======================================================================*/ | ||
131 | 92 | ||
132 | /** | 93 | /** |
133 | * socket drivers are expected to use the following callbacks in their | 94 | * Low-level PCMCIA socket drivers need to register with the PCCard |
95 | * core using pcmcia_register_socket. | ||
96 | * | ||
97 | * socket drivers are expected to use the following callbacks in their | ||
134 | * .drv struct: | 98 | * .drv struct: |
135 | * - pcmcia_socket_dev_suspend | 99 | * - pcmcia_socket_dev_suspend |
136 | * - pcmcia_socket_dev_resume | 100 | * - pcmcia_socket_dev_resume |
@@ -230,8 +194,8 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
230 | } | 194 | } |
231 | 195 | ||
232 | /* try to obtain a socket number [yes, it gets ugly if we | 196 | /* try to obtain a socket number [yes, it gets ugly if we |
233 | * register more than 2^sizeof(unsigned int) pcmcia | 197 | * register more than 2^sizeof(unsigned int) pcmcia |
234 | * sockets... but the socket number is deprecated | 198 | * sockets... but the socket number is deprecated |
235 | * anyways, so I don't care] */ | 199 | * anyways, so I don't care] */ |
236 | down_write(&pcmcia_socket_list_rwsem); | 200 | down_write(&pcmcia_socket_list_rwsem); |
237 | if (list_empty(&pcmcia_socket_list)) | 201 | if (list_empty(&pcmcia_socket_list)) |
@@ -340,54 +304,49 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr) | |||
340 | EXPORT_SYMBOL(pcmcia_get_socket_by_nr); | 304 | EXPORT_SYMBOL(pcmcia_get_socket_by_nr); |
341 | 305 | ||
342 | 306 | ||
343 | /*====================================================================== | 307 | /** |
344 | 308 | * socket_setup() and shutdown_socket() are called by the main event | |
345 | socket_setup() and shutdown_socket() are called by the main event | 309 | * handler when card insertion and removal events are received. |
346 | handler when card insertion and removal events are received. | 310 | * socket_setup() turns on socket power and resets the socket, in two stages. |
347 | socket_setup() turns on socket power and resets the socket, in two stages. | 311 | * shutdown_socket() unconfigures a socket and turns off socket power. |
348 | shutdown_socket() unconfigures a socket and turns off socket power. | 312 | */ |
349 | |||
350 | ======================================================================*/ | ||
351 | |||
352 | static void shutdown_socket(struct pcmcia_socket *s) | 313 | static void shutdown_socket(struct pcmcia_socket *s) |
353 | { | 314 | { |
354 | cs_dbg(s, 1, "shutdown_socket\n"); | 315 | cs_dbg(s, 1, "shutdown_socket\n"); |
355 | 316 | ||
356 | /* Blank out the socket state */ | 317 | /* Blank out the socket state */ |
357 | s->socket = dead_socket; | 318 | s->socket = dead_socket; |
358 | s->ops->init(s); | 319 | s->ops->init(s); |
359 | s->ops->set_socket(s, &s->socket); | 320 | s->ops->set_socket(s, &s->socket); |
360 | s->irq.AssignedIRQ = s->irq.Config = 0; | 321 | s->irq.AssignedIRQ = s->irq.Config = 0; |
361 | s->lock_count = 0; | 322 | s->lock_count = 0; |
362 | destroy_cis_cache(s); | 323 | destroy_cis_cache(s); |
363 | #ifdef CONFIG_CARDBUS | 324 | #ifdef CONFIG_CARDBUS |
364 | cb_free(s); | 325 | cb_free(s); |
365 | #endif | 326 | #endif |
366 | s->functions = 0; | 327 | s->functions = 0; |
367 | if (s->config) { | 328 | if (s->config) { |
368 | kfree(s->config); | 329 | kfree(s->config); |
369 | s->config = NULL; | 330 | s->config = NULL; |
370 | } | ||
371 | |||
372 | { | ||
373 | int status; | ||
374 | s->ops->get_status(s, &status); | ||
375 | if (status & SS_POWERON) { | ||
376 | printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s); | ||
377 | } | 331 | } |
378 | } | ||
379 | } /* shutdown_socket */ | ||
380 | 332 | ||
381 | /*====================================================================== | 333 | { |
334 | int status; | ||
335 | s->ops->get_status(s, &status); | ||
336 | if (status & SS_POWERON) { | ||
337 | printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s); | ||
338 | } | ||
339 | } | ||
340 | } /* shutdown_socket */ | ||
382 | 341 | ||
383 | The central event handler. Send_event() sends an event to the | ||
384 | 16-bit subsystem, which then calls the relevant device drivers. | ||
385 | Parse_events() interprets the event bits from | ||
386 | a card status change report. Do_shutdown() handles the high | ||
387 | priority stuff associated with a card removal. | ||
388 | |||
389 | ======================================================================*/ | ||
390 | 342 | ||
343 | /** | ||
344 | * The central event handler. Send_event() sends an event to the | ||
345 | * 16-bit subsystem, which then calls the relevant device drivers. | ||
346 | * Parse_events() interprets the event bits from | ||
347 | * a card status change report. Do_shutdown() handles the high | ||
348 | * priority stuff associated with a card removal. | ||
349 | */ | ||
391 | 350 | ||
392 | /* NOTE: send_event needs to be called with skt->sem held. */ | 351 | /* NOTE: send_event needs to be called with skt->sem held. */ |
393 | 352 | ||
@@ -746,420 +705,9 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events) | |||
746 | wake_up(&s->thread_wait); | 705 | wake_up(&s->thread_wait); |
747 | } | 706 | } |
748 | } /* pcmcia_parse_events */ | 707 | } /* pcmcia_parse_events */ |
708 | EXPORT_SYMBOL(pcmcia_parse_events); | ||
749 | 709 | ||
750 | 710 | ||
751 | /*====================================================================== | ||
752 | |||
753 | Special stuff for managing IO windows, because they are scarce. | ||
754 | |||
755 | ======================================================================*/ | ||
756 | |||
757 | static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, | ||
758 | ioaddr_t num, u_int lines) | ||
759 | { | ||
760 | int i; | ||
761 | kio_addr_t try, align; | ||
762 | |||
763 | align = (*base) ? (lines ? 1<<lines : 0) : 1; | ||
764 | if (align && (align < num)) { | ||
765 | if (*base) { | ||
766 | cs_dbg(s, 0, "odd IO request: num %#x align %#lx\n", | ||
767 | num, align); | ||
768 | align = 0; | ||
769 | } else | ||
770 | while (align && (align < num)) align <<= 1; | ||
771 | } | ||
772 | if (*base & ~(align-1)) { | ||
773 | cs_dbg(s, 0, "odd IO request: base %#x align %#lx\n", | ||
774 | *base, align); | ||
775 | align = 0; | ||
776 | } | ||
777 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { | ||
778 | *base = s->io_offset | (*base & 0x0fff); | ||
779 | return 0; | ||
780 | } | ||
781 | /* Check for an already-allocated window that must conflict with | ||
782 | what was asked for. It is a hack because it does not catch all | ||
783 | potential conflicts, just the most obvious ones. */ | ||
784 | for (i = 0; i < MAX_IO_WIN; i++) | ||
785 | if ((s->io[i].NumPorts != 0) && | ||
786 | ((s->io[i].BasePort & (align-1)) == *base)) | ||
787 | return 1; | ||
788 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
789 | if (s->io[i].NumPorts == 0) { | ||
790 | s->io[i].res = find_io_region(*base, num, align, s); | ||
791 | if (s->io[i].res) { | ||
792 | s->io[i].Attributes = attr; | ||
793 | s->io[i].BasePort = *base = s->io[i].res->start; | ||
794 | s->io[i].NumPorts = s->io[i].InUse = num; | ||
795 | break; | ||
796 | } else | ||
797 | return 1; | ||
798 | } else if (s->io[i].Attributes != attr) | ||
799 | continue; | ||
800 | /* Try to extend top of window */ | ||
801 | try = s->io[i].BasePort + s->io[i].NumPorts; | ||
802 | if ((*base == 0) || (*base == try)) | ||
803 | if (adjust_io_region(s->io[i].res, s->io[i].res->start, | ||
804 | s->io[i].res->end + num, s) == 0) { | ||
805 | *base = try; | ||
806 | s->io[i].NumPorts += num; | ||
807 | s->io[i].InUse += num; | ||
808 | break; | ||
809 | } | ||
810 | /* Try to extend bottom of window */ | ||
811 | try = s->io[i].BasePort - num; | ||
812 | if ((*base == 0) || (*base == try)) | ||
813 | if (adjust_io_region(s->io[i].res, s->io[i].res->start - num, | ||
814 | s->io[i].res->end, s) == 0) { | ||
815 | s->io[i].BasePort = *base = try; | ||
816 | s->io[i].NumPorts += num; | ||
817 | s->io[i].InUse += num; | ||
818 | break; | ||
819 | } | ||
820 | } | ||
821 | return (i == MAX_IO_WIN); | ||
822 | } /* alloc_io_space */ | ||
823 | |||
824 | static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, | ||
825 | ioaddr_t num) | ||
826 | { | ||
827 | int i; | ||
828 | |||
829 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
830 | if ((s->io[i].BasePort <= base) && | ||
831 | (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) { | ||
832 | s->io[i].InUse -= num; | ||
833 | /* Free the window if no one else is using it */ | ||
834 | if (s->io[i].InUse == 0) { | ||
835 | s->io[i].NumPorts = 0; | ||
836 | release_resource(s->io[i].res); | ||
837 | kfree(s->io[i].res); | ||
838 | s->io[i].res = NULL; | ||
839 | } | ||
840 | } | ||
841 | } | ||
842 | } | ||
843 | |||
844 | /*====================================================================== | ||
845 | |||
846 | Access_configuration_register() reads and writes configuration | ||
847 | registers in attribute memory. Memory window 0 is reserved for | ||
848 | this and the tuple reading services. | ||
849 | |||
850 | ======================================================================*/ | ||
851 | |||
852 | int pccard_access_configuration_register(struct pcmcia_socket *s, | ||
853 | unsigned int function, | ||
854 | conf_reg_t *reg) | ||
855 | { | ||
856 | config_t *c; | ||
857 | int addr; | ||
858 | u_char val; | ||
859 | |||
860 | if (!s || !s->config) | ||
861 | return CS_NO_CARD; | ||
862 | |||
863 | c = &s->config[function]; | ||
864 | |||
865 | if (c == NULL) | ||
866 | return CS_NO_CARD; | ||
867 | |||
868 | if (!(c->state & CONFIG_LOCKED)) | ||
869 | return CS_CONFIGURATION_LOCKED; | ||
870 | |||
871 | addr = (c->ConfigBase + reg->Offset) >> 1; | ||
872 | |||
873 | switch (reg->Action) { | ||
874 | case CS_READ: | ||
875 | read_cis_mem(s, 1, addr, 1, &val); | ||
876 | reg->Value = val; | ||
877 | break; | ||
878 | case CS_WRITE: | ||
879 | val = reg->Value; | ||
880 | write_cis_mem(s, 1, addr, 1, &val); | ||
881 | break; | ||
882 | default: | ||
883 | return CS_BAD_ARGS; | ||
884 | break; | ||
885 | } | ||
886 | return CS_SUCCESS; | ||
887 | } /* access_configuration_register */ | ||
888 | EXPORT_SYMBOL(pccard_access_configuration_register); | ||
889 | |||
890 | |||
891 | /*====================================================================*/ | ||
892 | |||
893 | int pccard_get_configuration_info(struct pcmcia_socket *s, | ||
894 | unsigned int function, | ||
895 | config_info_t *config) | ||
896 | { | ||
897 | config_t *c; | ||
898 | |||
899 | if (!(s->state & SOCKET_PRESENT)) | ||
900 | return CS_NO_CARD; | ||
901 | |||
902 | config->Function = function; | ||
903 | |||
904 | #ifdef CONFIG_CARDBUS | ||
905 | if (s->state & SOCKET_CARDBUS) { | ||
906 | memset(config, 0, sizeof(config_info_t)); | ||
907 | config->Vcc = s->socket.Vcc; | ||
908 | config->Vpp1 = config->Vpp2 = s->socket.Vpp; | ||
909 | config->Option = s->cb_dev->subordinate->number; | ||
910 | if (s->state & SOCKET_CARDBUS_CONFIG) { | ||
911 | config->Attributes = CONF_VALID_CLIENT; | ||
912 | config->IntType = INT_CARDBUS; | ||
913 | config->AssignedIRQ = s->irq.AssignedIRQ; | ||
914 | if (config->AssignedIRQ) | ||
915 | config->Attributes |= CONF_ENABLE_IRQ; | ||
916 | config->BasePort1 = s->io[0].BasePort; | ||
917 | config->NumPorts1 = s->io[0].NumPorts; | ||
918 | } | ||
919 | return CS_SUCCESS; | ||
920 | } | ||
921 | #endif | ||
922 | |||
923 | c = (s->config != NULL) ? &s->config[function] : NULL; | ||
924 | |||
925 | if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { | ||
926 | config->Attributes = 0; | ||
927 | config->Vcc = s->socket.Vcc; | ||
928 | config->Vpp1 = config->Vpp2 = s->socket.Vpp; | ||
929 | return CS_SUCCESS; | ||
930 | } | ||
931 | |||
932 | /* !!! This is a hack !!! */ | ||
933 | memcpy(&config->Attributes, &c->Attributes, sizeof(config_t)); | ||
934 | config->Attributes |= CONF_VALID_CLIENT; | ||
935 | config->CardValues = c->CardValues; | ||
936 | config->IRQAttributes = c->irq.Attributes; | ||
937 | config->AssignedIRQ = s->irq.AssignedIRQ; | ||
938 | config->BasePort1 = c->io.BasePort1; | ||
939 | config->NumPorts1 = c->io.NumPorts1; | ||
940 | config->Attributes1 = c->io.Attributes1; | ||
941 | config->BasePort2 = c->io.BasePort2; | ||
942 | config->NumPorts2 = c->io.NumPorts2; | ||
943 | config->Attributes2 = c->io.Attributes2; | ||
944 | config->IOAddrLines = c->io.IOAddrLines; | ||
945 | |||
946 | return CS_SUCCESS; | ||
947 | } /* get_configuration_info */ | ||
948 | EXPORT_SYMBOL(pccard_get_configuration_info); | ||
949 | |||
950 | /*====================================================================== | ||
951 | |||
952 | Return information about this version of Card Services. | ||
953 | |||
954 | ======================================================================*/ | ||
955 | |||
956 | int pcmcia_get_card_services_info(servinfo_t *info) | ||
957 | { | ||
958 | unsigned int socket_count = 0; | ||
959 | struct list_head *tmp; | ||
960 | info->Signature[0] = 'C'; | ||
961 | info->Signature[1] = 'S'; | ||
962 | down_read(&pcmcia_socket_list_rwsem); | ||
963 | list_for_each(tmp, &pcmcia_socket_list) | ||
964 | socket_count++; | ||
965 | up_read(&pcmcia_socket_list_rwsem); | ||
966 | info->Count = socket_count; | ||
967 | info->Revision = CS_RELEASE_CODE; | ||
968 | info->CSLevel = 0x0210; | ||
969 | info->VendorString = (char *)release; | ||
970 | return CS_SUCCESS; | ||
971 | } /* get_card_services_info */ | ||
972 | |||
973 | |||
974 | /*====================================================================*/ | ||
975 | |||
976 | int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req) | ||
977 | { | ||
978 | window_t *win; | ||
979 | int w; | ||
980 | |||
981 | if (!s || !(s->state & SOCKET_PRESENT)) | ||
982 | return CS_NO_CARD; | ||
983 | for (w = idx; w < MAX_WIN; w++) | ||
984 | if (s->state & SOCKET_WIN_REQ(w)) break; | ||
985 | if (w == MAX_WIN) | ||
986 | return CS_NO_MORE_ITEMS; | ||
987 | win = &s->win[w]; | ||
988 | req->Base = win->ctl.res->start; | ||
989 | req->Size = win->ctl.res->end - win->ctl.res->start + 1; | ||
990 | req->AccessSpeed = win->ctl.speed; | ||
991 | req->Attributes = 0; | ||
992 | if (win->ctl.flags & MAP_ATTRIB) | ||
993 | req->Attributes |= WIN_MEMORY_TYPE_AM; | ||
994 | if (win->ctl.flags & MAP_ACTIVE) | ||
995 | req->Attributes |= WIN_ENABLE; | ||
996 | if (win->ctl.flags & MAP_16BIT) | ||
997 | req->Attributes |= WIN_DATA_WIDTH_16; | ||
998 | if (win->ctl.flags & MAP_USE_WAIT) | ||
999 | req->Attributes |= WIN_USE_WAIT; | ||
1000 | *handle = win; | ||
1001 | return CS_SUCCESS; | ||
1002 | } /* get_window */ | ||
1003 | EXPORT_SYMBOL(pcmcia_get_window); | ||
1004 | |||
1005 | /*===================================================================== | ||
1006 | |||
1007 | Return the PCI device associated with a card.. | ||
1008 | |||
1009 | ======================================================================*/ | ||
1010 | |||
1011 | #ifdef CONFIG_CARDBUS | ||
1012 | |||
1013 | struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s) | ||
1014 | { | ||
1015 | if (!s || !(s->state & SOCKET_CARDBUS)) | ||
1016 | return NULL; | ||
1017 | |||
1018 | return s->cb_dev->subordinate; | ||
1019 | } | ||
1020 | |||
1021 | EXPORT_SYMBOL(pcmcia_lookup_bus); | ||
1022 | |||
1023 | #endif | ||
1024 | |||
1025 | /*====================================================================== | ||
1026 | |||
1027 | Get the current socket state bits. We don't support the latched | ||
1028 | SocketState yet: I haven't seen any point for it. | ||
1029 | |||
1030 | ======================================================================*/ | ||
1031 | |||
1032 | int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status) | ||
1033 | { | ||
1034 | config_t *c; | ||
1035 | int val; | ||
1036 | |||
1037 | s->ops->get_status(s, &val); | ||
1038 | status->CardState = status->SocketState = 0; | ||
1039 | status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; | ||
1040 | status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; | ||
1041 | status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0; | ||
1042 | status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0; | ||
1043 | if (s->state & SOCKET_SUSPEND) | ||
1044 | status->CardState |= CS_EVENT_PM_SUSPEND; | ||
1045 | if (!(s->state & SOCKET_PRESENT)) | ||
1046 | return CS_NO_CARD; | ||
1047 | |||
1048 | c = (s->config != NULL) ? &s->config[function] : NULL; | ||
1049 | if ((c != NULL) && (c->state & CONFIG_LOCKED) && | ||
1050 | (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { | ||
1051 | u_char reg; | ||
1052 | if (c->Present & PRESENT_PIN_REPLACE) { | ||
1053 | read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); | ||
1054 | status->CardState |= | ||
1055 | (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; | ||
1056 | status->CardState |= | ||
1057 | (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0; | ||
1058 | status->CardState |= | ||
1059 | (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0; | ||
1060 | status->CardState |= | ||
1061 | (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0; | ||
1062 | } else { | ||
1063 | /* No PRR? Then assume we're always ready */ | ||
1064 | status->CardState |= CS_EVENT_READY_CHANGE; | ||
1065 | } | ||
1066 | if (c->Present & PRESENT_EXT_STATUS) { | ||
1067 | read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); | ||
1068 | status->CardState |= | ||
1069 | (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; | ||
1070 | } | ||
1071 | return CS_SUCCESS; | ||
1072 | } | ||
1073 | status->CardState |= | ||
1074 | (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0; | ||
1075 | status->CardState |= | ||
1076 | (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0; | ||
1077 | status->CardState |= | ||
1078 | (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0; | ||
1079 | status->CardState |= | ||
1080 | (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; | ||
1081 | return CS_SUCCESS; | ||
1082 | } /* get_status */ | ||
1083 | EXPORT_SYMBOL(pccard_get_status); | ||
1084 | |||
1085 | /*====================================================================== | ||
1086 | |||
1087 | Change the card address of an already open memory window. | ||
1088 | |||
1089 | ======================================================================*/ | ||
1090 | |||
1091 | int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) | ||
1092 | { | ||
1093 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | ||
1094 | return CS_BAD_HANDLE; | ||
1095 | req->Page = 0; | ||
1096 | req->CardOffset = win->ctl.card_start; | ||
1097 | return CS_SUCCESS; | ||
1098 | } /* get_mem_page */ | ||
1099 | |||
1100 | int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) | ||
1101 | { | ||
1102 | struct pcmcia_socket *s; | ||
1103 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | ||
1104 | return CS_BAD_HANDLE; | ||
1105 | if (req->Page != 0) | ||
1106 | return CS_BAD_PAGE; | ||
1107 | s = win->sock; | ||
1108 | win->ctl.card_start = req->CardOffset; | ||
1109 | if (s->ops->set_mem_map(s, &win->ctl) != 0) | ||
1110 | return CS_BAD_OFFSET; | ||
1111 | return CS_SUCCESS; | ||
1112 | } /* map_mem_page */ | ||
1113 | |||
1114 | /*====================================================================== | ||
1115 | |||
1116 | Modify a locked socket configuration | ||
1117 | |||
1118 | ======================================================================*/ | ||
1119 | |||
1120 | int pcmcia_modify_configuration(client_handle_t handle, | ||
1121 | modconf_t *mod) | ||
1122 | { | ||
1123 | struct pcmcia_socket *s; | ||
1124 | config_t *c; | ||
1125 | |||
1126 | if (CHECK_HANDLE(handle)) | ||
1127 | return CS_BAD_HANDLE; | ||
1128 | s = SOCKET(handle); c = CONFIG(handle); | ||
1129 | if (!(s->state & SOCKET_PRESENT)) | ||
1130 | return CS_NO_CARD; | ||
1131 | if (!(c->state & CONFIG_LOCKED)) | ||
1132 | return CS_CONFIGURATION_LOCKED; | ||
1133 | |||
1134 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { | ||
1135 | if (mod->Attributes & CONF_ENABLE_IRQ) { | ||
1136 | c->Attributes |= CONF_ENABLE_IRQ; | ||
1137 | s->socket.io_irq = s->irq.AssignedIRQ; | ||
1138 | } else { | ||
1139 | c->Attributes &= ~CONF_ENABLE_IRQ; | ||
1140 | s->socket.io_irq = 0; | ||
1141 | } | ||
1142 | s->ops->set_socket(s, &s->socket); | ||
1143 | } | ||
1144 | |||
1145 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) | ||
1146 | return CS_BAD_VCC; | ||
1147 | |||
1148 | /* We only allow changing Vpp1 and Vpp2 to the same value */ | ||
1149 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | ||
1150 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | ||
1151 | if (mod->Vpp1 != mod->Vpp2) | ||
1152 | return CS_BAD_VPP; | ||
1153 | c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1; | ||
1154 | if (s->ops->set_socket(s, &s->socket)) | ||
1155 | return CS_BAD_VPP; | ||
1156 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | ||
1157 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) | ||
1158 | return CS_BAD_VPP; | ||
1159 | |||
1160 | return CS_SUCCESS; | ||
1161 | } /* modify_configuration */ | ||
1162 | |||
1163 | /* register pcmcia_callback */ | 711 | /* register pcmcia_callback */ |
1164 | int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) | 712 | int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) |
1165 | { | 713 | { |
@@ -1188,543 +736,16 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) | |||
1188 | } | 736 | } |
1189 | EXPORT_SYMBOL(pccard_register_pcmcia); | 737 | EXPORT_SYMBOL(pccard_register_pcmcia); |
1190 | 738 | ||
1191 | /*====================================================================*/ | ||
1192 | 739 | ||
1193 | int pcmcia_release_configuration(client_handle_t handle) | 740 | /* I'm not sure which "reset" function this is supposed to use, |
1194 | { | 741 | * but for now, it uses the low-level interface's reset, not the |
1195 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 742 | * CIS register. |
1196 | struct pcmcia_socket *s; | 743 | */ |
1197 | int i; | ||
1198 | |||
1199 | if (CHECK_HANDLE(handle) || | ||
1200 | !(handle->state & CLIENT_CONFIG_LOCKED)) | ||
1201 | return CS_BAD_HANDLE; | ||
1202 | handle->state &= ~CLIENT_CONFIG_LOCKED; | ||
1203 | s = SOCKET(handle); | ||
1204 | |||
1205 | #ifdef CONFIG_CARDBUS | ||
1206 | if (handle->state & CLIENT_CARDBUS) | ||
1207 | return CS_SUCCESS; | ||
1208 | #endif | ||
1209 | |||
1210 | if (!(handle->state & CLIENT_STALE)) { | ||
1211 | config_t *c = CONFIG(handle); | ||
1212 | if (--(s->lock_count) == 0) { | ||
1213 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ | ||
1214 | s->socket.Vpp = 0; | ||
1215 | s->socket.io_irq = 0; | ||
1216 | s->ops->set_socket(s, &s->socket); | ||
1217 | } | ||
1218 | if (c->state & CONFIG_IO_REQ) | ||
1219 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
1220 | if (s->io[i].NumPorts == 0) | ||
1221 | continue; | ||
1222 | s->io[i].Config--; | ||
1223 | if (s->io[i].Config != 0) | ||
1224 | continue; | ||
1225 | io.map = i; | ||
1226 | s->ops->set_io_map(s, &io); | ||
1227 | } | ||
1228 | c->state &= ~CONFIG_LOCKED; | ||
1229 | } | ||
1230 | |||
1231 | return CS_SUCCESS; | ||
1232 | } /* release_configuration */ | ||
1233 | |||
1234 | /*====================================================================== | ||
1235 | |||
1236 | Release_io() releases the I/O ranges allocated by a client. This | ||
1237 | may be invoked some time after a card ejection has already dumped | ||
1238 | the actual socket configuration, so if the client is "stale", we | ||
1239 | don't bother checking the port ranges against the current socket | ||
1240 | values. | ||
1241 | |||
1242 | ======================================================================*/ | ||
1243 | |||
1244 | int pcmcia_release_io(client_handle_t handle, io_req_t *req) | ||
1245 | { | ||
1246 | struct pcmcia_socket *s; | ||
1247 | |||
1248 | if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ)) | ||
1249 | return CS_BAD_HANDLE; | ||
1250 | handle->state &= ~CLIENT_IO_REQ; | ||
1251 | s = SOCKET(handle); | ||
1252 | |||
1253 | #ifdef CONFIG_CARDBUS | ||
1254 | if (handle->state & CLIENT_CARDBUS) | ||
1255 | return CS_SUCCESS; | ||
1256 | #endif | ||
1257 | |||
1258 | if (!(handle->state & CLIENT_STALE)) { | ||
1259 | config_t *c = CONFIG(handle); | ||
1260 | if (c->state & CONFIG_LOCKED) | ||
1261 | return CS_CONFIGURATION_LOCKED; | ||
1262 | if ((c->io.BasePort1 != req->BasePort1) || | ||
1263 | (c->io.NumPorts1 != req->NumPorts1) || | ||
1264 | (c->io.BasePort2 != req->BasePort2) || | ||
1265 | (c->io.NumPorts2 != req->NumPorts2)) | ||
1266 | return CS_BAD_ARGS; | ||
1267 | c->state &= ~CONFIG_IO_REQ; | ||
1268 | } | ||
1269 | |||
1270 | release_io_space(s, req->BasePort1, req->NumPorts1); | ||
1271 | if (req->NumPorts2) | ||
1272 | release_io_space(s, req->BasePort2, req->NumPorts2); | ||
1273 | |||
1274 | return CS_SUCCESS; | ||
1275 | } /* release_io */ | ||
1276 | |||
1277 | /*====================================================================*/ | ||
1278 | |||
1279 | int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) | ||
1280 | { | ||
1281 | struct pcmcia_socket *s; | ||
1282 | if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ)) | ||
1283 | return CS_BAD_HANDLE; | ||
1284 | handle->state &= ~CLIENT_IRQ_REQ; | ||
1285 | s = SOCKET(handle); | ||
1286 | |||
1287 | if (!(handle->state & CLIENT_STALE)) { | ||
1288 | config_t *c = CONFIG(handle); | ||
1289 | if (c->state & CONFIG_LOCKED) | ||
1290 | return CS_CONFIGURATION_LOCKED; | ||
1291 | if (c->irq.Attributes != req->Attributes) | ||
1292 | return CS_BAD_ATTRIBUTE; | ||
1293 | if (s->irq.AssignedIRQ != req->AssignedIRQ) | ||
1294 | return CS_BAD_IRQ; | ||
1295 | if (--s->irq.Config == 0) { | ||
1296 | c->state &= ~CONFIG_IRQ_REQ; | ||
1297 | s->irq.AssignedIRQ = 0; | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1301 | if (req->Attributes & IRQ_HANDLE_PRESENT) { | ||
1302 | free_irq(req->AssignedIRQ, req->Instance); | ||
1303 | } | ||
1304 | |||
1305 | #ifdef CONFIG_PCMCIA_PROBE | ||
1306 | pcmcia_used_irq[req->AssignedIRQ]--; | ||
1307 | #endif | ||
1308 | |||
1309 | return CS_SUCCESS; | ||
1310 | } /* cs_release_irq */ | ||
1311 | |||
1312 | /*====================================================================*/ | ||
1313 | |||
1314 | int pcmcia_release_window(window_handle_t win) | ||
1315 | { | ||
1316 | struct pcmcia_socket *s; | ||
1317 | |||
1318 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | ||
1319 | return CS_BAD_HANDLE; | ||
1320 | s = win->sock; | ||
1321 | if (!(win->handle->state & CLIENT_WIN_REQ(win->index))) | ||
1322 | return CS_BAD_HANDLE; | ||
1323 | |||
1324 | /* Shut down memory window */ | ||
1325 | win->ctl.flags &= ~MAP_ACTIVE; | ||
1326 | s->ops->set_mem_map(s, &win->ctl); | ||
1327 | s->state &= ~SOCKET_WIN_REQ(win->index); | ||
1328 | |||
1329 | /* Release system memory */ | ||
1330 | if (win->ctl.res) { | ||
1331 | release_resource(win->ctl.res); | ||
1332 | kfree(win->ctl.res); | ||
1333 | win->ctl.res = NULL; | ||
1334 | } | ||
1335 | win->handle->state &= ~CLIENT_WIN_REQ(win->index); | ||
1336 | |||
1337 | win->magic = 0; | ||
1338 | |||
1339 | return CS_SUCCESS; | ||
1340 | } /* release_window */ | ||
1341 | |||
1342 | /*====================================================================*/ | ||
1343 | |||
1344 | int pcmcia_request_configuration(client_handle_t handle, | ||
1345 | config_req_t *req) | ||
1346 | { | ||
1347 | int i; | ||
1348 | u_int base; | ||
1349 | struct pcmcia_socket *s; | ||
1350 | config_t *c; | ||
1351 | pccard_io_map iomap; | ||
1352 | |||
1353 | if (CHECK_HANDLE(handle)) | ||
1354 | return CS_BAD_HANDLE; | ||
1355 | s = SOCKET(handle); | ||
1356 | if (!(s->state & SOCKET_PRESENT)) | ||
1357 | return CS_NO_CARD; | ||
1358 | |||
1359 | #ifdef CONFIG_CARDBUS | ||
1360 | if (handle->state & CLIENT_CARDBUS) | ||
1361 | return CS_UNSUPPORTED_MODE; | ||
1362 | #endif | ||
1363 | |||
1364 | if (req->IntType & INT_CARDBUS) | ||
1365 | return CS_UNSUPPORTED_MODE; | ||
1366 | c = CONFIG(handle); | ||
1367 | if (c->state & CONFIG_LOCKED) | ||
1368 | return CS_CONFIGURATION_LOCKED; | ||
1369 | |||
1370 | /* Do power control. We don't allow changes in Vcc. */ | ||
1371 | if (s->socket.Vcc != req->Vcc) | ||
1372 | return CS_BAD_VCC; | ||
1373 | if (req->Vpp1 != req->Vpp2) | ||
1374 | return CS_BAD_VPP; | ||
1375 | s->socket.Vpp = req->Vpp1; | ||
1376 | if (s->ops->set_socket(s, &s->socket)) | ||
1377 | return CS_BAD_VPP; | ||
1378 | |||
1379 | c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1; | ||
1380 | |||
1381 | /* Pick memory or I/O card, DMA mode, interrupt */ | ||
1382 | c->IntType = req->IntType; | ||
1383 | c->Attributes = req->Attributes; | ||
1384 | if (req->IntType & INT_MEMORY_AND_IO) | ||
1385 | s->socket.flags |= SS_IOCARD; | ||
1386 | if (req->IntType & INT_ZOOMED_VIDEO) | ||
1387 | s->socket.flags |= SS_ZVCARD | SS_IOCARD; | ||
1388 | if (req->Attributes & CONF_ENABLE_DMA) | ||
1389 | s->socket.flags |= SS_DMA_MODE; | ||
1390 | if (req->Attributes & CONF_ENABLE_SPKR) | ||
1391 | s->socket.flags |= SS_SPKR_ENA; | ||
1392 | if (req->Attributes & CONF_ENABLE_IRQ) | ||
1393 | s->socket.io_irq = s->irq.AssignedIRQ; | ||
1394 | else | ||
1395 | s->socket.io_irq = 0; | ||
1396 | s->ops->set_socket(s, &s->socket); | ||
1397 | s->lock_count++; | ||
1398 | |||
1399 | /* Set up CIS configuration registers */ | ||
1400 | base = c->ConfigBase = req->ConfigBase; | ||
1401 | c->Present = c->CardValues = req->Present; | ||
1402 | if (req->Present & PRESENT_COPY) { | ||
1403 | c->Copy = req->Copy; | ||
1404 | write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); | ||
1405 | } | ||
1406 | if (req->Present & PRESENT_OPTION) { | ||
1407 | if (s->functions == 1) { | ||
1408 | c->Option = req->ConfigIndex & COR_CONFIG_MASK; | ||
1409 | } else { | ||
1410 | c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; | ||
1411 | c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; | ||
1412 | if (req->Present & PRESENT_IOBASE_0) | ||
1413 | c->Option |= COR_ADDR_DECODE; | ||
1414 | } | ||
1415 | if (c->state & CONFIG_IRQ_REQ) | ||
1416 | if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) | ||
1417 | c->Option |= COR_LEVEL_REQ; | ||
1418 | write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); | ||
1419 | mdelay(40); | ||
1420 | } | ||
1421 | if (req->Present & PRESENT_STATUS) { | ||
1422 | c->Status = req->Status; | ||
1423 | write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); | ||
1424 | } | ||
1425 | if (req->Present & PRESENT_PIN_REPLACE) { | ||
1426 | c->Pin = req->Pin; | ||
1427 | write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); | ||
1428 | } | ||
1429 | if (req->Present & PRESENT_EXT_STATUS) { | ||
1430 | c->ExtStatus = req->ExtStatus; | ||
1431 | write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); | ||
1432 | } | ||
1433 | if (req->Present & PRESENT_IOBASE_0) { | ||
1434 | u_char b = c->io.BasePort1 & 0xff; | ||
1435 | write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); | ||
1436 | b = (c->io.BasePort1 >> 8) & 0xff; | ||
1437 | write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); | ||
1438 | } | ||
1439 | if (req->Present & PRESENT_IOSIZE) { | ||
1440 | u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1; | ||
1441 | write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); | ||
1442 | } | ||
1443 | |||
1444 | /* Configure I/O windows */ | ||
1445 | if (c->state & CONFIG_IO_REQ) { | ||
1446 | iomap.speed = io_speed; | ||
1447 | for (i = 0; i < MAX_IO_WIN; i++) | ||
1448 | if (s->io[i].NumPorts != 0) { | ||
1449 | iomap.map = i; | ||
1450 | iomap.flags = MAP_ACTIVE; | ||
1451 | switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) { | ||
1452 | case IO_DATA_PATH_WIDTH_16: | ||
1453 | iomap.flags |= MAP_16BIT; break; | ||
1454 | case IO_DATA_PATH_WIDTH_AUTO: | ||
1455 | iomap.flags |= MAP_AUTOSZ; break; | ||
1456 | default: | ||
1457 | break; | ||
1458 | } | ||
1459 | iomap.start = s->io[i].BasePort; | ||
1460 | iomap.stop = iomap.start + s->io[i].NumPorts - 1; | ||
1461 | s->ops->set_io_map(s, &iomap); | ||
1462 | s->io[i].Config++; | ||
1463 | } | ||
1464 | } | ||
1465 | |||
1466 | c->state |= CONFIG_LOCKED; | ||
1467 | handle->state |= CLIENT_CONFIG_LOCKED; | ||
1468 | return CS_SUCCESS; | ||
1469 | } /* request_configuration */ | ||
1470 | |||
1471 | /*====================================================================== | ||
1472 | |||
1473 | Request_io() reserves ranges of port addresses for a socket. | ||
1474 | I have not implemented range sharing or alias addressing. | ||
1475 | |||
1476 | ======================================================================*/ | ||
1477 | |||
1478 | int pcmcia_request_io(client_handle_t handle, io_req_t *req) | ||
1479 | { | ||
1480 | struct pcmcia_socket *s; | ||
1481 | config_t *c; | ||
1482 | |||
1483 | if (CHECK_HANDLE(handle)) | ||
1484 | return CS_BAD_HANDLE; | ||
1485 | s = SOCKET(handle); | ||
1486 | if (!(s->state & SOCKET_PRESENT)) | ||
1487 | return CS_NO_CARD; | ||
1488 | |||
1489 | if (handle->state & CLIENT_CARDBUS) { | ||
1490 | #ifdef CONFIG_CARDBUS | ||
1491 | handle->state |= CLIENT_IO_REQ; | ||
1492 | return CS_SUCCESS; | ||
1493 | #else | ||
1494 | return CS_UNSUPPORTED_FUNCTION; | ||
1495 | #endif | ||
1496 | } | ||
1497 | |||
1498 | if (!req) | ||
1499 | return CS_UNSUPPORTED_MODE; | ||
1500 | c = CONFIG(handle); | ||
1501 | if (c->state & CONFIG_LOCKED) | ||
1502 | return CS_CONFIGURATION_LOCKED; | ||
1503 | if (c->state & CONFIG_IO_REQ) | ||
1504 | return CS_IN_USE; | ||
1505 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) | ||
1506 | return CS_BAD_ATTRIBUTE; | ||
1507 | if ((req->NumPorts2 > 0) && | ||
1508 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) | ||
1509 | return CS_BAD_ATTRIBUTE; | ||
1510 | |||
1511 | if (alloc_io_space(s, req->Attributes1, &req->BasePort1, | ||
1512 | req->NumPorts1, req->IOAddrLines)) | ||
1513 | return CS_IN_USE; | ||
1514 | |||
1515 | if (req->NumPorts2) { | ||
1516 | if (alloc_io_space(s, req->Attributes2, &req->BasePort2, | ||
1517 | req->NumPorts2, req->IOAddrLines)) { | ||
1518 | release_io_space(s, req->BasePort1, req->NumPorts1); | ||
1519 | return CS_IN_USE; | ||
1520 | } | ||
1521 | } | ||
1522 | |||
1523 | c->io = *req; | ||
1524 | c->state |= CONFIG_IO_REQ; | ||
1525 | handle->state |= CLIENT_IO_REQ; | ||
1526 | return CS_SUCCESS; | ||
1527 | } /* request_io */ | ||
1528 | |||
1529 | /*====================================================================== | ||
1530 | |||
1531 | Request_irq() reserves an irq for this client. | ||
1532 | |||
1533 | Also, since Linux only reserves irq's when they are actually | ||
1534 | hooked, we don't guarantee that an irq will still be available | ||
1535 | when the configuration is locked. Now that I think about it, | ||
1536 | there might be a way to fix this using a dummy handler. | ||
1537 | |||
1538 | ======================================================================*/ | ||
1539 | |||
1540 | #ifdef CONFIG_PCMCIA_PROBE | ||
1541 | static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
1542 | { | ||
1543 | return IRQ_NONE; | ||
1544 | } | ||
1545 | #endif | ||
1546 | |||
1547 | int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) | ||
1548 | { | ||
1549 | struct pcmcia_socket *s; | ||
1550 | config_t *c; | ||
1551 | int ret = CS_IN_USE, irq = 0; | ||
1552 | struct pcmcia_device *p_dev = handle_to_pdev(handle); | ||
1553 | |||
1554 | if (CHECK_HANDLE(handle)) | ||
1555 | return CS_BAD_HANDLE; | ||
1556 | s = SOCKET(handle); | ||
1557 | if (!(s->state & SOCKET_PRESENT)) | ||
1558 | return CS_NO_CARD; | ||
1559 | c = CONFIG(handle); | ||
1560 | if (c->state & CONFIG_LOCKED) | ||
1561 | return CS_CONFIGURATION_LOCKED; | ||
1562 | if (c->state & CONFIG_IRQ_REQ) | ||
1563 | return CS_IN_USE; | ||
1564 | |||
1565 | #ifdef CONFIG_PCMCIA_PROBE | ||
1566 | if (s->irq.AssignedIRQ != 0) { | ||
1567 | /* If the interrupt is already assigned, it must be the same */ | ||
1568 | irq = s->irq.AssignedIRQ; | ||
1569 | } else { | ||
1570 | int try; | ||
1571 | u32 mask = s->irq_mask; | ||
1572 | void *data = NULL; | ||
1573 | |||
1574 | for (try = 0; try < 64; try++) { | ||
1575 | irq = try % 32; | ||
1576 | |||
1577 | /* marked as available by driver, and not blocked by userspace? */ | ||
1578 | if (!((mask >> irq) & 1)) | ||
1579 | continue; | ||
1580 | |||
1581 | /* avoid an IRQ which is already used by a PCMCIA card */ | ||
1582 | if ((try < 32) && pcmcia_used_irq[irq]) | ||
1583 | continue; | ||
1584 | |||
1585 | /* register the correct driver, if possible, of check whether | ||
1586 | * registering a dummy handle works, i.e. if the IRQ isn't | ||
1587 | * marked as used by the kernel resource management core */ | ||
1588 | ret = request_irq(irq, | ||
1589 | (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, | ||
1590 | ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || | ||
1591 | (s->functions > 1) || | ||
1592 | (irq == s->pci_irq)) ? SA_SHIRQ : 0, | ||
1593 | p_dev->dev.bus_id, | ||
1594 | (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); | ||
1595 | if (!ret) { | ||
1596 | if (!(req->Attributes & IRQ_HANDLE_PRESENT)) | ||
1597 | free_irq(irq, data); | ||
1598 | break; | ||
1599 | } | ||
1600 | } | ||
1601 | } | ||
1602 | #endif | ||
1603 | if (ret) { | ||
1604 | if (!s->pci_irq) | ||
1605 | return ret; | ||
1606 | irq = s->pci_irq; | ||
1607 | } | ||
1608 | |||
1609 | if (ret && req->Attributes & IRQ_HANDLE_PRESENT) { | ||
1610 | if (request_irq(irq, req->Handler, | ||
1611 | ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || | ||
1612 | (s->functions > 1) || | ||
1613 | (irq == s->pci_irq)) ? SA_SHIRQ : 0, | ||
1614 | p_dev->dev.bus_id, req->Instance)) | ||
1615 | return CS_IN_USE; | ||
1616 | } | ||
1617 | |||
1618 | c->irq.Attributes = req->Attributes; | ||
1619 | s->irq.AssignedIRQ = req->AssignedIRQ = irq; | ||
1620 | s->irq.Config++; | ||
1621 | |||
1622 | c->state |= CONFIG_IRQ_REQ; | ||
1623 | handle->state |= CLIENT_IRQ_REQ; | ||
1624 | |||
1625 | #ifdef CONFIG_PCMCIA_PROBE | ||
1626 | pcmcia_used_irq[irq]++; | ||
1627 | #endif | ||
1628 | |||
1629 | return CS_SUCCESS; | ||
1630 | } /* pcmcia_request_irq */ | ||
1631 | |||
1632 | /*====================================================================== | ||
1633 | |||
1634 | Request_window() establishes a mapping between card memory space | ||
1635 | and system memory space. | ||
1636 | |||
1637 | ======================================================================*/ | ||
1638 | |||
1639 | int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh) | ||
1640 | { | ||
1641 | struct pcmcia_socket *s; | ||
1642 | window_t *win; | ||
1643 | u_long align; | ||
1644 | int w; | ||
1645 | |||
1646 | if (CHECK_HANDLE(*handle)) | ||
1647 | return CS_BAD_HANDLE; | ||
1648 | s = (*handle)->Socket; | ||
1649 | if (!(s->state & SOCKET_PRESENT)) | ||
1650 | return CS_NO_CARD; | ||
1651 | if (req->Attributes & (WIN_PAGED | WIN_SHARED)) | ||
1652 | return CS_BAD_ATTRIBUTE; | ||
1653 | |||
1654 | /* Window size defaults to smallest available */ | ||
1655 | if (req->Size == 0) | ||
1656 | req->Size = s->map_size; | ||
1657 | align = (((s->features & SS_CAP_MEM_ALIGN) || | ||
1658 | (req->Attributes & WIN_STRICT_ALIGN)) ? | ||
1659 | req->Size : s->map_size); | ||
1660 | if (req->Size & (s->map_size-1)) | ||
1661 | return CS_BAD_SIZE; | ||
1662 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || | ||
1663 | (req->Base & (align-1))) | ||
1664 | return CS_BAD_BASE; | ||
1665 | if (req->Base) | ||
1666 | align = 0; | ||
1667 | |||
1668 | /* Allocate system memory window */ | ||
1669 | for (w = 0; w < MAX_WIN; w++) | ||
1670 | if (!(s->state & SOCKET_WIN_REQ(w))) break; | ||
1671 | if (w == MAX_WIN) | ||
1672 | return CS_OUT_OF_RESOURCE; | ||
1673 | |||
1674 | win = &s->win[w]; | ||
1675 | win->magic = WINDOW_MAGIC; | ||
1676 | win->index = w; | ||
1677 | win->handle = *handle; | ||
1678 | win->sock = s; | ||
1679 | |||
1680 | if (!(s->features & SS_CAP_STATIC_MAP)) { | ||
1681 | win->ctl.res = find_mem_region(req->Base, req->Size, align, | ||
1682 | (req->Attributes & WIN_MAP_BELOW_1MB), s); | ||
1683 | if (!win->ctl.res) | ||
1684 | return CS_IN_USE; | ||
1685 | } | ||
1686 | (*handle)->state |= CLIENT_WIN_REQ(w); | ||
1687 | |||
1688 | /* Configure the socket controller */ | ||
1689 | win->ctl.map = w+1; | ||
1690 | win->ctl.flags = 0; | ||
1691 | win->ctl.speed = req->AccessSpeed; | ||
1692 | if (req->Attributes & WIN_MEMORY_TYPE) | ||
1693 | win->ctl.flags |= MAP_ATTRIB; | ||
1694 | if (req->Attributes & WIN_ENABLE) | ||
1695 | win->ctl.flags |= MAP_ACTIVE; | ||
1696 | if (req->Attributes & WIN_DATA_WIDTH_16) | ||
1697 | win->ctl.flags |= MAP_16BIT; | ||
1698 | if (req->Attributes & WIN_USE_WAIT) | ||
1699 | win->ctl.flags |= MAP_USE_WAIT; | ||
1700 | win->ctl.card_start = 0; | ||
1701 | if (s->ops->set_mem_map(s, &win->ctl) != 0) | ||
1702 | return CS_BAD_ARGS; | ||
1703 | s->state |= SOCKET_WIN_REQ(w); | ||
1704 | |||
1705 | /* Return window handle */ | ||
1706 | if (s->features & SS_CAP_STATIC_MAP) { | ||
1707 | req->Base = win->ctl.static_start; | ||
1708 | } else { | ||
1709 | req->Base = win->ctl.res->start; | ||
1710 | } | ||
1711 | *wh = win; | ||
1712 | |||
1713 | return CS_SUCCESS; | ||
1714 | } /* request_window */ | ||
1715 | |||
1716 | /*====================================================================== | ||
1717 | |||
1718 | I'm not sure which "reset" function this is supposed to use, | ||
1719 | but for now, it uses the low-level interface's reset, not the | ||
1720 | CIS register. | ||
1721 | |||
1722 | ======================================================================*/ | ||
1723 | 744 | ||
1724 | int pccard_reset_card(struct pcmcia_socket *skt) | 745 | int pccard_reset_card(struct pcmcia_socket *skt) |
1725 | { | 746 | { |
1726 | int ret; | 747 | int ret; |
1727 | 748 | ||
1728 | cs_dbg(skt, 1, "resetting socket\n"); | 749 | cs_dbg(skt, 1, "resetting socket\n"); |
1729 | 750 | ||
1730 | down(&skt->skt_sem); | 751 | down(&skt->skt_sem); |
@@ -1757,17 +778,14 @@ int pccard_reset_card(struct pcmcia_socket *skt) | |||
1757 | } /* reset_card */ | 778 | } /* reset_card */ |
1758 | EXPORT_SYMBOL(pccard_reset_card); | 779 | EXPORT_SYMBOL(pccard_reset_card); |
1759 | 780 | ||
1760 | /*====================================================================== | ||
1761 | |||
1762 | These shut down or wake up a socket. They are sort of user | ||
1763 | initiated versions of the APM suspend and resume actions. | ||
1764 | |||
1765 | ======================================================================*/ | ||
1766 | 781 | ||
782 | /* These shut down or wake up a socket. They are sort of user | ||
783 | * initiated versions of the APM suspend and resume actions. | ||
784 | */ | ||
1767 | int pcmcia_suspend_card(struct pcmcia_socket *skt) | 785 | int pcmcia_suspend_card(struct pcmcia_socket *skt) |
1768 | { | 786 | { |
1769 | int ret; | 787 | int ret; |
1770 | 788 | ||
1771 | cs_dbg(skt, 1, "suspending socket\n"); | 789 | cs_dbg(skt, 1, "suspending socket\n"); |
1772 | 790 | ||
1773 | down(&skt->skt_sem); | 791 | down(&skt->skt_sem); |
@@ -1786,6 +804,8 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt) | |||
1786 | 804 | ||
1787 | return ret; | 805 | return ret; |
1788 | } /* suspend_card */ | 806 | } /* suspend_card */ |
807 | EXPORT_SYMBOL(pcmcia_suspend_card); | ||
808 | |||
1789 | 809 | ||
1790 | int pcmcia_resume_card(struct pcmcia_socket *skt) | 810 | int pcmcia_resume_card(struct pcmcia_socket *skt) |
1791 | { | 811 | { |
@@ -1809,13 +829,10 @@ int pcmcia_resume_card(struct pcmcia_socket *skt) | |||
1809 | 829 | ||
1810 | return ret; | 830 | return ret; |
1811 | } /* resume_card */ | 831 | } /* resume_card */ |
832 | EXPORT_SYMBOL(pcmcia_resume_card); | ||
1812 | 833 | ||
1813 | /*====================================================================== | ||
1814 | |||
1815 | These handle user requests to eject or insert a card. | ||
1816 | |||
1817 | ======================================================================*/ | ||
1818 | 834 | ||
835 | /* These handle user requests to eject or insert a card. */ | ||
1819 | int pcmcia_eject_card(struct pcmcia_socket *skt) | 836 | int pcmcia_eject_card(struct pcmcia_socket *skt) |
1820 | { | 837 | { |
1821 | int ret; | 838 | int ret; |
@@ -1842,6 +859,8 @@ int pcmcia_eject_card(struct pcmcia_socket *skt) | |||
1842 | 859 | ||
1843 | return ret; | 860 | return ret; |
1844 | } /* eject_card */ | 861 | } /* eject_card */ |
862 | EXPORT_SYMBOL(pcmcia_eject_card); | ||
863 | |||
1845 | 864 | ||
1846 | int pcmcia_insert_card(struct pcmcia_socket *skt) | 865 | int pcmcia_insert_card(struct pcmcia_socket *skt) |
1847 | { | 866 | { |
@@ -1865,37 +884,38 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) | |||
1865 | 884 | ||
1866 | return ret; | 885 | return ret; |
1867 | } /* insert_card */ | 886 | } /* insert_card */ |
887 | EXPORT_SYMBOL(pcmcia_insert_card); | ||
1868 | 888 | ||
1869 | /*====================================================================== | ||
1870 | 889 | ||
1871 | OS-specific module glue goes here | 890 | static int pcmcia_socket_hotplug(struct class_device *dev, char **envp, |
1872 | 891 | int num_envp, char *buffer, int buffer_size) | |
1873 | ======================================================================*/ | 892 | { |
1874 | /* in alpha order */ | 893 | struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); |
1875 | EXPORT_SYMBOL(pcmcia_eject_card); | 894 | int i = 0, length = 0; |
1876 | EXPORT_SYMBOL(pcmcia_get_card_services_info); | 895 | |
1877 | EXPORT_SYMBOL(pcmcia_get_mem_page); | 896 | if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, |
1878 | EXPORT_SYMBOL(pcmcia_insert_card); | 897 | &length, "SOCKET_NO=%u", s->sock)) |
1879 | EXPORT_SYMBOL(pcmcia_map_mem_page); | 898 | return -ENOMEM; |
1880 | EXPORT_SYMBOL(pcmcia_modify_configuration); | 899 | |
1881 | EXPORT_SYMBOL(pcmcia_release_configuration); | 900 | envp[i] = NULL; |
1882 | EXPORT_SYMBOL(pcmcia_release_io); | 901 | |
1883 | EXPORT_SYMBOL(pcmcia_release_irq); | 902 | return 0; |
1884 | EXPORT_SYMBOL(pcmcia_release_window); | 903 | } |
1885 | EXPORT_SYMBOL(pcmcia_replace_cis); | 904 | |
1886 | EXPORT_SYMBOL(pcmcia_request_configuration); | 905 | |
1887 | EXPORT_SYMBOL(pcmcia_request_io); | 906 | static struct completion pcmcia_unload; |
1888 | EXPORT_SYMBOL(pcmcia_request_irq); | 907 | |
1889 | EXPORT_SYMBOL(pcmcia_request_window); | 908 | static void pcmcia_release_socket_class(struct class *data) |
1890 | EXPORT_SYMBOL(pcmcia_resume_card); | 909 | { |
1891 | EXPORT_SYMBOL(pcmcia_suspend_card); | 910 | complete(&pcmcia_unload); |
911 | } | ||
1892 | 912 | ||
1893 | EXPORT_SYMBOL(dead_socket); | ||
1894 | EXPORT_SYMBOL(pcmcia_parse_events); | ||
1895 | 913 | ||
1896 | struct class pcmcia_socket_class = { | 914 | struct class pcmcia_socket_class = { |
1897 | .name = "pcmcia_socket", | 915 | .name = "pcmcia_socket", |
916 | .hotplug = pcmcia_socket_hotplug, | ||
1898 | .release = pcmcia_release_socket, | 917 | .release = pcmcia_release_socket, |
918 | .class_release = pcmcia_release_socket_class, | ||
1899 | }; | 919 | }; |
1900 | EXPORT_SYMBOL(pcmcia_socket_class); | 920 | EXPORT_SYMBOL(pcmcia_socket_class); |
1901 | 921 | ||
@@ -1903,9 +923,8 @@ EXPORT_SYMBOL(pcmcia_socket_class); | |||
1903 | static int __init init_pcmcia_cs(void) | 923 | static int __init init_pcmcia_cs(void) |
1904 | { | 924 | { |
1905 | int ret; | 925 | int ret; |
1906 | printk(KERN_INFO "%s\n", release); | ||
1907 | printk(KERN_INFO " %s\n", options); | ||
1908 | 926 | ||
927 | init_completion(&pcmcia_unload); | ||
1909 | ret = class_register(&pcmcia_socket_class); | 928 | ret = class_register(&pcmcia_socket_class); |
1910 | if (ret) | 929 | if (ret) |
1911 | return (ret); | 930 | return (ret); |
@@ -1914,13 +933,12 @@ static int __init init_pcmcia_cs(void) | |||
1914 | 933 | ||
1915 | static void __exit exit_pcmcia_cs(void) | 934 | static void __exit exit_pcmcia_cs(void) |
1916 | { | 935 | { |
1917 | printk(KERN_INFO "unloading Kernel Card Services\n"); | 936 | class_interface_unregister(&pccard_sysfs_interface); |
1918 | class_interface_unregister(&pccard_sysfs_interface); | 937 | class_unregister(&pcmcia_socket_class); |
1919 | class_unregister(&pcmcia_socket_class); | 938 | |
939 | wait_for_completion(&pcmcia_unload); | ||
1920 | } | 940 | } |
1921 | 941 | ||
1922 | subsys_initcall(init_pcmcia_cs); | 942 | subsys_initcall(init_pcmcia_cs); |
1923 | module_exit(exit_pcmcia_cs); | 943 | module_exit(exit_pcmcia_cs); |
1924 | 944 | ||
1925 | /*====================================================================*/ | ||
1926 | |||
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 7933a7db49d3..0b4c18edfa49 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -123,9 +123,9 @@ void cb_free(struct pcmcia_socket *s); | |||
123 | int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr); | 123 | int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr); |
124 | 124 | ||
125 | /* In cistpl.c */ | 125 | /* In cistpl.c */ |
126 | int read_cis_mem(struct pcmcia_socket *s, int attr, | 126 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, |
127 | u_int addr, u_int len, void *ptr); | 127 | u_int addr, u_int len, void *ptr); |
128 | void write_cis_mem(struct pcmcia_socket *s, int attr, | 128 | void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, |
129 | u_int addr, u_int len, void *ptr); | 129 | u_int addr, u_int len, void *ptr); |
130 | void release_cis_mem(struct pcmcia_socket *s); | 130 | void release_cis_mem(struct pcmcia_socket *s); |
131 | void destroy_cis_cache(struct pcmcia_socket *s); | 131 | void destroy_cis_cache(struct pcmcia_socket *s); |
@@ -134,13 +134,12 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t | |||
134 | 134 | ||
135 | /* In rsrc_mgr */ | 135 | /* In rsrc_mgr */ |
136 | void pcmcia_validate_mem(struct pcmcia_socket *s); | 136 | void pcmcia_validate_mem(struct pcmcia_socket *s); |
137 | struct resource *find_io_region(unsigned long base, int num, unsigned long align, | 137 | struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align, |
138 | struct pcmcia_socket *s); | 138 | struct pcmcia_socket *s); |
139 | int adjust_io_region(struct resource *res, unsigned long r_start, | 139 | int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start, |
140 | unsigned long r_end, struct pcmcia_socket *s); | 140 | unsigned long r_end, struct pcmcia_socket *s); |
141 | struct resource *find_mem_region(u_long base, u_long num, u_long align, | 141 | struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, |
142 | int low, struct pcmcia_socket *s); | 142 | int low, struct pcmcia_socket *s); |
143 | int adjust_resource_info(client_handle_t handle, adjust_t *adj); | ||
144 | void release_resource_db(struct pcmcia_socket *s); | 143 | void release_resource_db(struct pcmcia_socket *s); |
145 | 144 | ||
146 | /* In socket_sysfs.c */ | 145 | /* In socket_sysfs.c */ |
@@ -159,7 +158,7 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int f | |||
159 | struct pcmcia_callback{ | 158 | struct pcmcia_callback{ |
160 | struct module *owner; | 159 | struct module *owner; |
161 | int (*event) (struct pcmcia_socket *s, event_t event, int priority); | 160 | int (*event) (struct pcmcia_socket *s, event_t event, int priority); |
162 | int (*resources_done) (struct pcmcia_socket *s); | 161 | void (*requery) (struct pcmcia_socket *s); |
163 | }; | 162 | }; |
164 | 163 | ||
165 | int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); | 164 | int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 569e55feecfd..cabddd49f6ff 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -10,44 +10,29 @@ | |||
10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
11 | * | 11 | * |
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | * (C) 2003 - 2004 Dominik Brodowski | 13 | * (C) 2003 - 2005 Dominik Brodowski |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/kernel.h> | ||
21 | #include <linux/major.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
24 | #include <linux/slab.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <linux/fcntl.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/smp_lock.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/ioctl.h> | ||
31 | #include <linux/proc_fs.h> | ||
32 | #include <linux/poll.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/list.h> | 21 | #include <linux/list.h> |
35 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
36 | #include <linux/kref.h> | ||
37 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
38 | 24 | #include <linux/crc32.h> | |
39 | #include <asm/atomic.h> | 25 | #include <linux/firmware.h> |
40 | 26 | ||
41 | #define IN_CARD_SERVICES | 27 | #define IN_CARD_SERVICES |
42 | #include <pcmcia/version.h> | ||
43 | #include <pcmcia/cs_types.h> | 28 | #include <pcmcia/cs_types.h> |
44 | #include <pcmcia/cs.h> | 29 | #include <pcmcia/cs.h> |
45 | #include <pcmcia/bulkmem.h> | ||
46 | #include <pcmcia/cistpl.h> | 30 | #include <pcmcia/cistpl.h> |
47 | #include <pcmcia/ds.h> | 31 | #include <pcmcia/ds.h> |
48 | #include <pcmcia/ss.h> | 32 | #include <pcmcia/ss.h> |
49 | 33 | ||
50 | #include "cs_internal.h" | 34 | #include "cs_internal.h" |
35 | #include "ds_internal.h" | ||
51 | 36 | ||
52 | /*====================================================================*/ | 37 | /*====================================================================*/ |
53 | 38 | ||
@@ -70,49 +55,9 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644); | |||
70 | #define ds_dbg(lvl, fmt, arg...) do { } while (0) | 55 | #define ds_dbg(lvl, fmt, arg...) do { } while (0) |
71 | #endif | 56 | #endif |
72 | 57 | ||
73 | /*====================================================================*/ | 58 | spinlock_t pcmcia_dev_list_lock; |
74 | 59 | ||
75 | /* Device user information */ | 60 | static int unbind_request(struct pcmcia_socket *s); |
76 | #define MAX_EVENTS 32 | ||
77 | #define USER_MAGIC 0x7ea4 | ||
78 | #define CHECK_USER(u) \ | ||
79 | (((u) == NULL) || ((u)->user_magic != USER_MAGIC)) | ||
80 | typedef struct user_info_t { | ||
81 | u_int user_magic; | ||
82 | int event_head, event_tail; | ||
83 | event_t event[MAX_EVENTS]; | ||
84 | struct user_info_t *next; | ||
85 | struct pcmcia_bus_socket *socket; | ||
86 | } user_info_t; | ||
87 | |||
88 | /* Socket state information */ | ||
89 | struct pcmcia_bus_socket { | ||
90 | struct kref refcount; | ||
91 | struct pcmcia_callback callback; | ||
92 | int state; | ||
93 | user_info_t *user; | ||
94 | wait_queue_head_t queue; | ||
95 | struct pcmcia_socket *parent; | ||
96 | |||
97 | /* the PCMCIA devices connected to this socket (normally one, more | ||
98 | * for multifunction devices: */ | ||
99 | struct list_head devices_list; | ||
100 | u8 device_count; /* the number of devices, used | ||
101 | * only internally and subject | ||
102 | * to incorrectness and change */ | ||
103 | }; | ||
104 | static spinlock_t pcmcia_dev_list_lock; | ||
105 | |||
106 | #define DS_SOCKET_PRESENT 0x01 | ||
107 | #define DS_SOCKET_BUSY 0x02 | ||
108 | #define DS_SOCKET_REMOVAL_PENDING 0x10 | ||
109 | #define DS_SOCKET_DEAD 0x80 | ||
110 | |||
111 | /*====================================================================*/ | ||
112 | |||
113 | static int major_dev = -1; | ||
114 | |||
115 | static int unbind_request(struct pcmcia_bus_socket *s); | ||
116 | 61 | ||
117 | /*====================================================================*/ | 62 | /*====================================================================*/ |
118 | 63 | ||
@@ -213,7 +158,7 @@ static const lookup_t service_table[] = { | |||
213 | }; | 158 | }; |
214 | 159 | ||
215 | 160 | ||
216 | int pcmcia_report_error(client_handle_t handle, error_info_t *err) | 161 | static int pcmcia_report_error(client_handle_t handle, error_info_t *err) |
217 | { | 162 | { |
218 | int i; | 163 | int i; |
219 | char *serv; | 164 | char *serv; |
@@ -243,7 +188,6 @@ int pcmcia_report_error(client_handle_t handle, error_info_t *err) | |||
243 | 188 | ||
244 | return CS_SUCCESS; | 189 | return CS_SUCCESS; |
245 | } /* report_error */ | 190 | } /* report_error */ |
246 | EXPORT_SYMBOL(pcmcia_report_error); | ||
247 | 191 | ||
248 | /* end of code which was in cs.c before */ | 192 | /* end of code which was in cs.c before */ |
249 | 193 | ||
@@ -256,29 +200,101 @@ void cs_error(client_handle_t handle, int func, int ret) | |||
256 | } | 200 | } |
257 | EXPORT_SYMBOL(cs_error); | 201 | EXPORT_SYMBOL(cs_error); |
258 | 202 | ||
259 | /*======================================================================*/ | ||
260 | |||
261 | static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info); | ||
262 | static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr); | ||
263 | 203 | ||
264 | static void pcmcia_release_bus_socket(struct kref *refcount) | 204 | static void pcmcia_check_driver(struct pcmcia_driver *p_drv) |
265 | { | 205 | { |
266 | struct pcmcia_bus_socket *s = container_of(refcount, struct pcmcia_bus_socket, refcount); | 206 | struct pcmcia_device_id *did = p_drv->id_table; |
267 | pcmcia_put_socket(s->parent); | 207 | unsigned int i; |
268 | kfree(s); | 208 | u32 hash; |
209 | |||
210 | while (did && did->match_flags) { | ||
211 | for (i=0; i<4; i++) { | ||
212 | if (!did->prod_id[i]) | ||
213 | continue; | ||
214 | |||
215 | hash = crc32(0, did->prod_id[i], strlen(did->prod_id[i])); | ||
216 | if (hash == did->prod_id_hash[i]) | ||
217 | continue; | ||
218 | |||
219 | printk(KERN_DEBUG "pcmcia: %s: invalid hash for " | ||
220 | "product string \"%s\": is 0x%x, should " | ||
221 | "be 0x%x\n", p_drv->drv.name, did->prod_id[i], | ||
222 | did->prod_id_hash[i], hash); | ||
223 | printk(KERN_DEBUG "pcmcia: see " | ||
224 | "Documentation/pcmcia/devicetable.txt for " | ||
225 | "details\n"); | ||
226 | } | ||
227 | did++; | ||
228 | } | ||
229 | |||
230 | return; | ||
269 | } | 231 | } |
270 | 232 | ||
271 | static void pcmcia_put_bus_socket(struct pcmcia_bus_socket *s) | 233 | |
234 | #ifdef CONFIG_PCMCIA_LOAD_CIS | ||
235 | |||
236 | /** | ||
237 | * pcmcia_load_firmware - load CIS from userspace if device-provided is broken | ||
238 | * @dev - the pcmcia device which needs a CIS override | ||
239 | * @filename - requested filename in /lib/firmware/cis/ | ||
240 | * | ||
241 | * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if | ||
242 | * the one provided by the card is broken. The firmware files reside in | ||
243 | * /lib/firmware/cis/ in userspace. | ||
244 | */ | ||
245 | static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | ||
272 | { | 246 | { |
273 | kref_put(&s->refcount, pcmcia_release_bus_socket); | 247 | struct pcmcia_socket *s = dev->socket; |
248 | const struct firmware *fw; | ||
249 | char path[20]; | ||
250 | int ret=-ENOMEM; | ||
251 | cisdump_t *cis; | ||
252 | |||
253 | if (!filename) | ||
254 | return -EINVAL; | ||
255 | |||
256 | ds_dbg(1, "trying to load firmware %s\n", filename); | ||
257 | |||
258 | if (strlen(filename) > 14) | ||
259 | return -EINVAL; | ||
260 | |||
261 | snprintf(path, 20, "%s", filename); | ||
262 | |||
263 | if (request_firmware(&fw, path, &dev->dev) == 0) { | ||
264 | if (fw->size >= CISTPL_MAX_CIS_SIZE) | ||
265 | goto release; | ||
266 | |||
267 | cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL); | ||
268 | if (!cis) | ||
269 | goto release; | ||
270 | |||
271 | memset(cis, 0, sizeof(cisdump_t)); | ||
272 | |||
273 | cis->Length = fw->size + 1; | ||
274 | memcpy(cis->Data, fw->data, fw->size); | ||
275 | |||
276 | if (!pcmcia_replace_cis(s, cis)) | ||
277 | ret = 0; | ||
278 | } | ||
279 | release: | ||
280 | release_firmware(fw); | ||
281 | |||
282 | return (ret); | ||
274 | } | 283 | } |
275 | 284 | ||
276 | static struct pcmcia_bus_socket *pcmcia_get_bus_socket(struct pcmcia_bus_socket *s) | 285 | #else /* !CONFIG_PCMCIA_LOAD_CIS */ |
286 | |||
287 | static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | ||
277 | { | 288 | { |
278 | kref_get(&s->refcount); | 289 | return -ENODEV; |
279 | return (s); | ||
280 | } | 290 | } |
281 | 291 | ||
292 | #endif | ||
293 | |||
294 | |||
295 | /*======================================================================*/ | ||
296 | |||
297 | |||
282 | /** | 298 | /** |
283 | * pcmcia_register_driver - register a PCMCIA driver with the bus core | 299 | * pcmcia_register_driver - register a PCMCIA driver with the bus core |
284 | * | 300 | * |
@@ -292,6 +308,8 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) | |||
292 | if (!driver) | 308 | if (!driver) |
293 | return -EINVAL; | 309 | return -EINVAL; |
294 | 310 | ||
311 | pcmcia_check_driver(driver); | ||
312 | |||
295 | /* initialize common fields */ | 313 | /* initialize common fields */ |
296 | driver->drv.bus = &pcmcia_bus_type; | 314 | driver->drv.bus = &pcmcia_bus_type; |
297 | driver->drv.owner = driver->owner; | 315 | driver->drv.owner = driver->owner; |
@@ -311,42 +329,10 @@ void pcmcia_unregister_driver(struct pcmcia_driver *driver) | |||
311 | } | 329 | } |
312 | EXPORT_SYMBOL(pcmcia_unregister_driver); | 330 | EXPORT_SYMBOL(pcmcia_unregister_driver); |
313 | 331 | ||
314 | #ifdef CONFIG_PROC_FS | ||
315 | static struct proc_dir_entry *proc_pccard = NULL; | ||
316 | |||
317 | static int proc_read_drivers_callback(struct device_driver *driver, void *d) | ||
318 | { | ||
319 | char **p = d; | ||
320 | struct pcmcia_driver *p_drv = container_of(driver, | ||
321 | struct pcmcia_driver, drv); | ||
322 | |||
323 | *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name, | ||
324 | #ifdef CONFIG_MODULE_UNLOAD | ||
325 | (p_drv->owner) ? module_refcount(p_drv->owner) : 1 | ||
326 | #else | ||
327 | 1 | ||
328 | #endif | ||
329 | ); | ||
330 | d = (void *) p; | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int proc_read_drivers(char *buf, char **start, off_t pos, | ||
336 | int count, int *eof, void *data) | ||
337 | { | ||
338 | char *p = buf; | ||
339 | |||
340 | bus_for_each_drv(&pcmcia_bus_type, NULL, | ||
341 | (void *) &p, proc_read_drivers_callback); | ||
342 | |||
343 | return (p - buf); | ||
344 | } | ||
345 | #endif | ||
346 | 332 | ||
347 | /* pcmcia_device handling */ | 333 | /* pcmcia_device handling */ |
348 | 334 | ||
349 | static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) | 335 | struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) |
350 | { | 336 | { |
351 | struct device *tmp_dev; | 337 | struct device *tmp_dev; |
352 | tmp_dev = get_device(&p_dev->dev); | 338 | tmp_dev = get_device(&p_dev->dev); |
@@ -355,7 +341,7 @@ static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) | |||
355 | return to_pcmcia_dev(tmp_dev); | 341 | return to_pcmcia_dev(tmp_dev); |
356 | } | 342 | } |
357 | 343 | ||
358 | static void pcmcia_put_dev(struct pcmcia_device *p_dev) | 344 | void pcmcia_put_dev(struct pcmcia_device *p_dev) |
359 | { | 345 | { |
360 | if (p_dev) | 346 | if (p_dev) |
361 | put_device(&p_dev->dev); | 347 | put_device(&p_dev->dev); |
@@ -365,7 +351,7 @@ static void pcmcia_release_dev(struct device *dev) | |||
365 | { | 351 | { |
366 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 352 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
367 | ds_dbg(1, "releasing dev %p\n", p_dev); | 353 | ds_dbg(1, "releasing dev %p\n", p_dev); |
368 | pcmcia_put_bus_socket(p_dev->socket->pcmcia); | 354 | pcmcia_put_socket(p_dev->socket); |
369 | kfree(p_dev); | 355 | kfree(p_dev); |
370 | } | 356 | } |
371 | 357 | ||
@@ -500,34 +486,38 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
500 | */ | 486 | */ |
501 | static DECLARE_MUTEX(device_add_lock); | 487 | static DECLARE_MUTEX(device_add_lock); |
502 | 488 | ||
503 | static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned int function) | 489 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) |
504 | { | 490 | { |
505 | struct pcmcia_device *p_dev; | 491 | struct pcmcia_device *p_dev; |
506 | unsigned long flags; | 492 | unsigned long flags; |
507 | 493 | ||
508 | s = pcmcia_get_bus_socket(s); | 494 | s = pcmcia_get_socket(s); |
509 | if (!s) | 495 | if (!s) |
510 | return NULL; | 496 | return NULL; |
511 | 497 | ||
512 | down(&device_add_lock); | 498 | down(&device_add_lock); |
513 | 499 | ||
500 | /* max of 2 devices per card */ | ||
501 | if (s->device_count == 2) | ||
502 | goto err_put; | ||
503 | |||
514 | p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); | 504 | p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); |
515 | if (!p_dev) | 505 | if (!p_dev) |
516 | goto err_put; | 506 | goto err_put; |
517 | memset(p_dev, 0, sizeof(struct pcmcia_device)); | 507 | memset(p_dev, 0, sizeof(struct pcmcia_device)); |
518 | 508 | ||
519 | p_dev->socket = s->parent; | 509 | p_dev->socket = s; |
520 | p_dev->device_no = (s->device_count++); | 510 | p_dev->device_no = (s->device_count++); |
521 | p_dev->func = function; | 511 | p_dev->func = function; |
522 | 512 | ||
523 | p_dev->dev.bus = &pcmcia_bus_type; | 513 | p_dev->dev.bus = &pcmcia_bus_type; |
524 | p_dev->dev.parent = s->parent->dev.dev; | 514 | p_dev->dev.parent = s->dev.dev; |
525 | p_dev->dev.release = pcmcia_release_dev; | 515 | p_dev->dev.release = pcmcia_release_dev; |
526 | sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); | 516 | sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); |
527 | 517 | ||
528 | /* compat */ | 518 | /* compat */ |
529 | p_dev->client.client_magic = CLIENT_MAGIC; | 519 | p_dev->client.client_magic = CLIENT_MAGIC; |
530 | p_dev->client.Socket = s->parent; | 520 | p_dev->client.Socket = s; |
531 | p_dev->client.Function = function; | 521 | p_dev->client.Function = function; |
532 | p_dev->client.state = CLIENT_UNBOUND; | 522 | p_dev->client.state = CLIENT_UNBOUND; |
533 | 523 | ||
@@ -536,6 +526,8 @@ static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, uns | |||
536 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); | 526 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); |
537 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 527 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
538 | 528 | ||
529 | pcmcia_device_query(p_dev); | ||
530 | |||
539 | if (device_register(&p_dev->dev)) { | 531 | if (device_register(&p_dev->dev)) { |
540 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 532 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
541 | list_del(&p_dev->socket_device_list); | 533 | list_del(&p_dev->socket_device_list); |
@@ -553,7 +545,7 @@ static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, uns | |||
553 | s->device_count--; | 545 | s->device_count--; |
554 | err_put: | 546 | err_put: |
555 | up(&device_add_lock); | 547 | up(&device_add_lock); |
556 | pcmcia_put_bus_socket(s); | 548 | pcmcia_put_socket(s); |
557 | 549 | ||
558 | return NULL; | 550 | return NULL; |
559 | } | 551 | } |
@@ -584,23 +576,252 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
584 | /* this doesn't handle multifunction devices on one pcmcia function | 576 | /* this doesn't handle multifunction devices on one pcmcia function |
585 | * yet. */ | 577 | * yet. */ |
586 | for (i=0; i < no_funcs; i++) | 578 | for (i=0; i < no_funcs; i++) |
587 | pcmcia_device_add(s->pcmcia, i); | 579 | pcmcia_device_add(s, i); |
588 | 580 | ||
589 | return (ret); | 581 | return (ret); |
590 | } | 582 | } |
591 | 583 | ||
592 | 584 | ||
585 | static void pcmcia_delayed_add_pseudo_device(void *data) | ||
586 | { | ||
587 | struct pcmcia_socket *s = data; | ||
588 | pcmcia_device_add(s, 0); | ||
589 | s->pcmcia_state.device_add_pending = 0; | ||
590 | } | ||
591 | |||
592 | static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) | ||
593 | { | ||
594 | if (!s->pcmcia_state.device_add_pending) { | ||
595 | schedule_work(&s->device_add); | ||
596 | s->pcmcia_state.device_add_pending = 1; | ||
597 | } | ||
598 | return; | ||
599 | } | ||
600 | |||
601 | static int pcmcia_requery(struct device *dev, void * _data) | ||
602 | { | ||
603 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
604 | if (!p_dev->dev.driver) | ||
605 | pcmcia_device_query(p_dev); | ||
606 | |||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static void pcmcia_bus_rescan(struct pcmcia_socket *skt) | ||
611 | { | ||
612 | int no_devices=0; | ||
613 | unsigned long flags; | ||
614 | |||
615 | /* must be called with skt_sem held */ | ||
616 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
617 | if (list_empty(&skt->devices_list)) | ||
618 | no_devices=1; | ||
619 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
620 | |||
621 | /* if no devices were added for this socket yet because of | ||
622 | * missing resource information or other trouble, we need to | ||
623 | * do this now. */ | ||
624 | if (no_devices) { | ||
625 | int ret = pcmcia_card_add(skt); | ||
626 | if (ret) | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | /* some device information might have changed because of a CIS | ||
631 | * update or because we can finally read it correctly... so | ||
632 | * determine it again, overwriting old values if necessary. */ | ||
633 | bus_for_each_dev(&pcmcia_bus_type, NULL, NULL, pcmcia_requery); | ||
634 | |||
635 | /* we re-scan all devices, not just the ones connected to this | ||
636 | * socket. This does not matter, though. */ | ||
637 | bus_rescan_devices(&pcmcia_bus_type); | ||
638 | } | ||
639 | |||
640 | static inline int pcmcia_devmatch(struct pcmcia_device *dev, | ||
641 | struct pcmcia_device_id *did) | ||
642 | { | ||
643 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) { | ||
644 | if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id)) | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID) { | ||
649 | if ((!dev->has_card_id) || (dev->card_id != did->card_id)) | ||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION) { | ||
654 | if (dev->func != did->function) | ||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1) { | ||
659 | if (!dev->prod_id[0]) | ||
660 | return 0; | ||
661 | if (strcmp(did->prod_id[0], dev->prod_id[0])) | ||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2) { | ||
666 | if (!dev->prod_id[1]) | ||
667 | return 0; | ||
668 | if (strcmp(did->prod_id[1], dev->prod_id[1])) | ||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3) { | ||
673 | if (!dev->prod_id[2]) | ||
674 | return 0; | ||
675 | if (strcmp(did->prod_id[2], dev->prod_id[2])) | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4) { | ||
680 | if (!dev->prod_id[3]) | ||
681 | return 0; | ||
682 | if (strcmp(did->prod_id[3], dev->prod_id[3])) | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { | ||
687 | /* handle pseudo multifunction devices: | ||
688 | * there are at most two pseudo multifunction devices. | ||
689 | * if we're matching against the first, schedule a | ||
690 | * call which will then check whether there are two | ||
691 | * pseudo devices, and if not, add the second one. | ||
692 | */ | ||
693 | if (dev->device_no == 0) | ||
694 | pcmcia_add_pseudo_device(dev->socket); | ||
695 | |||
696 | if (dev->device_no != did->device_no) | ||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { | ||
701 | if ((!dev->has_func_id) || (dev->func_id != did->func_id)) | ||
702 | return 0; | ||
703 | |||
704 | /* if this is a pseudo-multi-function device, | ||
705 | * we need explicit matches */ | ||
706 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) | ||
707 | return 0; | ||
708 | if (dev->device_no) | ||
709 | return 0; | ||
710 | |||
711 | /* also, FUNC_ID matching needs to be activated by userspace | ||
712 | * after it has re-checked that there is no possible module | ||
713 | * with a prod_id/manf_id/card_id match. | ||
714 | */ | ||
715 | if (!dev->allow_func_id_match) | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { | ||
720 | if (!dev->socket->fake_cis) | ||
721 | pcmcia_load_firmware(dev, did->cisfile); | ||
722 | |||
723 | if (!dev->socket->fake_cis) | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) { | ||
728 | int i; | ||
729 | for (i=0; i<4; i++) | ||
730 | if (dev->prod_id[i]) | ||
731 | return 0; | ||
732 | if (dev->has_manf_id || dev->has_card_id || dev->has_func_id) | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | dev->dev.driver_data = (void *) did; | ||
737 | |||
738 | return 1; | ||
739 | } | ||
740 | |||
741 | |||
593 | static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { | 742 | static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { |
594 | struct pcmcia_device * p_dev = to_pcmcia_dev(dev); | 743 | struct pcmcia_device * p_dev = to_pcmcia_dev(dev); |
595 | struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); | 744 | struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); |
745 | struct pcmcia_device_id *did = p_drv->id_table; | ||
596 | 746 | ||
597 | /* matching by cardmgr */ | 747 | /* matching by cardmgr */ |
598 | if (p_dev->cardmgr == p_drv) | 748 | if (p_dev->cardmgr == p_drv) |
599 | return 1; | 749 | return 1; |
600 | 750 | ||
751 | while (did && did->match_flags) { | ||
752 | if (pcmcia_devmatch(p_dev, did)) | ||
753 | return 1; | ||
754 | did++; | ||
755 | } | ||
756 | |||
601 | return 0; | 757 | return 0; |
602 | } | 758 | } |
603 | 759 | ||
760 | #ifdef CONFIG_HOTPLUG | ||
761 | |||
762 | static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp, | ||
763 | char *buffer, int buffer_size) | ||
764 | { | ||
765 | struct pcmcia_device *p_dev; | ||
766 | int i, length = 0; | ||
767 | u32 hash[4] = { 0, 0, 0, 0}; | ||
768 | |||
769 | if (!dev) | ||
770 | return -ENODEV; | ||
771 | |||
772 | p_dev = to_pcmcia_dev(dev); | ||
773 | |||
774 | /* calculate hashes */ | ||
775 | for (i=0; i<4; i++) { | ||
776 | if (!p_dev->prod_id[i]) | ||
777 | continue; | ||
778 | hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); | ||
779 | } | ||
780 | |||
781 | i = 0; | ||
782 | |||
783 | if (add_hotplug_env_var(envp, num_envp, &i, | ||
784 | buffer, buffer_size, &length, | ||
785 | "SOCKET_NO=%u", | ||
786 | p_dev->socket->sock)) | ||
787 | return -ENOMEM; | ||
788 | |||
789 | if (add_hotplug_env_var(envp, num_envp, &i, | ||
790 | buffer, buffer_size, &length, | ||
791 | "DEVICE_NO=%02X", | ||
792 | p_dev->device_no)) | ||
793 | return -ENOMEM; | ||
794 | |||
795 | if (add_hotplug_env_var(envp, num_envp, &i, | ||
796 | buffer, buffer_size, &length, | ||
797 | "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" | ||
798 | "pa%08Xpb%08Xpc%08Xpd%08X", | ||
799 | p_dev->has_manf_id ? p_dev->manf_id : 0, | ||
800 | p_dev->has_card_id ? p_dev->card_id : 0, | ||
801 | p_dev->has_func_id ? p_dev->func_id : 0, | ||
802 | p_dev->func, | ||
803 | p_dev->device_no, | ||
804 | hash[0], | ||
805 | hash[1], | ||
806 | hash[2], | ||
807 | hash[3])) | ||
808 | return -ENOMEM; | ||
809 | |||
810 | envp[i] = NULL; | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | #else | ||
816 | |||
817 | static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp, | ||
818 | char *buffer, int buffer_size) | ||
819 | { | ||
820 | return -ENODEV; | ||
821 | } | ||
822 | |||
823 | #endif | ||
824 | |||
604 | /************************ per-device sysfs output ***************************/ | 825 | /************************ per-device sysfs output ***************************/ |
605 | 826 | ||
606 | #define pcmcia_device_attr(field, test, format) \ | 827 | #define pcmcia_device_attr(field, test, format) \ |
@@ -626,6 +847,43 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]); | |||
626 | pcmcia_device_stringattr(prod_id3, prod_id[2]); | 847 | pcmcia_device_stringattr(prod_id3, prod_id[2]); |
627 | pcmcia_device_stringattr(prod_id4, prod_id[3]); | 848 | pcmcia_device_stringattr(prod_id4, prod_id[3]); |
628 | 849 | ||
850 | static ssize_t modalias_show(struct device *dev, char *buf) | ||
851 | { | ||
852 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
853 | int i; | ||
854 | u32 hash[4] = { 0, 0, 0, 0}; | ||
855 | |||
856 | /* calculate hashes */ | ||
857 | for (i=0; i<4; i++) { | ||
858 | if (!p_dev->prod_id[i]) | ||
859 | continue; | ||
860 | hash[i] = crc32(0,p_dev->prod_id[i],strlen(p_dev->prod_id[i])); | ||
861 | } | ||
862 | return sprintf(buf, "pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" | ||
863 | "pa%08Xpb%08Xpc%08Xpd%08X\n", | ||
864 | p_dev->has_manf_id ? p_dev->manf_id : 0, | ||
865 | p_dev->has_card_id ? p_dev->card_id : 0, | ||
866 | p_dev->has_func_id ? p_dev->func_id : 0, | ||
867 | p_dev->func, p_dev->device_no, | ||
868 | hash[0], hash[1], hash[2], hash[3]); | ||
869 | } | ||
870 | |||
871 | static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | ||
872 | struct device_attribute *attr, const char *buf, size_t count) | ||
873 | { | ||
874 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
875 | if (!count) | ||
876 | return -EINVAL; | ||
877 | |||
878 | down(&p_dev->socket->skt_sem); | ||
879 | p_dev->allow_func_id_match = 1; | ||
880 | up(&p_dev->socket->skt_sem); | ||
881 | |||
882 | bus_rescan_devices(&pcmcia_bus_type); | ||
883 | |||
884 | return count; | ||
885 | } | ||
886 | |||
629 | static struct device_attribute pcmcia_dev_attrs[] = { | 887 | static struct device_attribute pcmcia_dev_attrs[] = { |
630 | __ATTR(function, 0444, func_show, NULL), | 888 | __ATTR(function, 0444, func_show, NULL), |
631 | __ATTR_RO(func_id), | 889 | __ATTR_RO(func_id), |
@@ -635,46 +893,14 @@ static struct device_attribute pcmcia_dev_attrs[] = { | |||
635 | __ATTR_RO(prod_id2), | 893 | __ATTR_RO(prod_id2), |
636 | __ATTR_RO(prod_id3), | 894 | __ATTR_RO(prod_id3), |
637 | __ATTR_RO(prod_id4), | 895 | __ATTR_RO(prod_id4), |
896 | __ATTR_RO(modalias), | ||
897 | __ATTR(allow_func_id_match, 0200, NULL, pcmcia_store_allow_func_id_match), | ||
638 | __ATTR_NULL, | 898 | __ATTR_NULL, |
639 | }; | 899 | }; |
640 | 900 | ||
641 | 901 | ||
642 | /*====================================================================== | 902 | /*====================================================================== |
643 | 903 | ||
644 | These manage a ring buffer of events pending for one user process | ||
645 | |||
646 | ======================================================================*/ | ||
647 | |||
648 | static int queue_empty(user_info_t *user) | ||
649 | { | ||
650 | return (user->event_head == user->event_tail); | ||
651 | } | ||
652 | |||
653 | static event_t get_queued_event(user_info_t *user) | ||
654 | { | ||
655 | user->event_tail = (user->event_tail+1) % MAX_EVENTS; | ||
656 | return user->event[user->event_tail]; | ||
657 | } | ||
658 | |||
659 | static void queue_event(user_info_t *user, event_t event) | ||
660 | { | ||
661 | user->event_head = (user->event_head+1) % MAX_EVENTS; | ||
662 | if (user->event_head == user->event_tail) | ||
663 | user->event_tail = (user->event_tail+1) % MAX_EVENTS; | ||
664 | user->event[user->event_head] = event; | ||
665 | } | ||
666 | |||
667 | static void handle_event(struct pcmcia_bus_socket *s, event_t event) | ||
668 | { | ||
669 | user_info_t *user; | ||
670 | for (user = s->user; user; user = user->next) | ||
671 | queue_event(user, event); | ||
672 | wake_up_interruptible(&s->queue); | ||
673 | } | ||
674 | |||
675 | |||
676 | /*====================================================================== | ||
677 | |||
678 | The card status event handler. | 904 | The card status event handler. |
679 | 905 | ||
680 | ======================================================================*/ | 906 | ======================================================================*/ |
@@ -706,21 +932,13 @@ static int send_event_callback(struct device *dev, void * _data) | |||
706 | 932 | ||
707 | static int send_event(struct pcmcia_socket *s, event_t event, int priority) | 933 | static int send_event(struct pcmcia_socket *s, event_t event, int priority) |
708 | { | 934 | { |
709 | int ret = 0; | ||
710 | struct send_event_data private; | 935 | struct send_event_data private; |
711 | struct pcmcia_bus_socket *skt = pcmcia_get_bus_socket(s->pcmcia); | ||
712 | |||
713 | if (!skt) | ||
714 | return 0; | ||
715 | 936 | ||
716 | private.skt = s; | 937 | private.skt = s; |
717 | private.event = event; | 938 | private.event = event; |
718 | private.priority = priority; | 939 | private.priority = priority; |
719 | 940 | ||
720 | ret = bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback); | 941 | return bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback); |
721 | |||
722 | pcmcia_put_bus_socket(skt); | ||
723 | return ret; | ||
724 | } /* send_event */ | 942 | } /* send_event */ |
725 | 943 | ||
726 | 944 | ||
@@ -731,25 +949,25 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority) | |||
731 | 949 | ||
732 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | 950 | static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) |
733 | { | 951 | { |
734 | struct pcmcia_bus_socket *s = skt->pcmcia; | 952 | struct pcmcia_socket *s = pcmcia_get_socket(skt); |
735 | int ret = 0; | 953 | int ret = 0; |
736 | 954 | ||
737 | ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", | 955 | ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", |
738 | event, priority, s); | 956 | event, priority, skt); |
739 | 957 | ||
740 | switch (event) { | 958 | switch (event) { |
741 | 959 | ||
742 | case CS_EVENT_CARD_REMOVAL: | 960 | case CS_EVENT_CARD_REMOVAL: |
743 | s->state &= ~DS_SOCKET_PRESENT; | 961 | s->pcmcia_state.present = 0; |
744 | send_event(skt, event, priority); | 962 | send_event(skt, event, priority); |
745 | unbind_request(s); | 963 | unbind_request(skt); |
746 | handle_event(s, event); | 964 | handle_event(skt, event); |
747 | break; | 965 | break; |
748 | 966 | ||
749 | case CS_EVENT_CARD_INSERTION: | 967 | case CS_EVENT_CARD_INSERTION: |
750 | s->state |= DS_SOCKET_PRESENT; | 968 | s->pcmcia_state.present = 1; |
751 | pcmcia_card_add(skt); | 969 | pcmcia_card_add(skt); |
752 | handle_event(s, event); | 970 | handle_event(skt, event); |
753 | break; | 971 | break; |
754 | 972 | ||
755 | case CS_EVENT_EJECTION_REQUEST: | 973 | case CS_EVENT_EJECTION_REQUEST: |
@@ -757,137 +975,22 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
757 | break; | 975 | break; |
758 | 976 | ||
759 | default: | 977 | default: |
760 | handle_event(s, event); | 978 | handle_event(skt, event); |
761 | send_event(skt, event, priority); | 979 | send_event(skt, event, priority); |
762 | break; | 980 | break; |
763 | } | 981 | } |
764 | 982 | ||
983 | pcmcia_put_socket(s); | ||
984 | |||
765 | return 0; | 985 | return 0; |
766 | } /* ds_event */ | 986 | } /* ds_event */ |
767 | 987 | ||
768 | 988 | ||
769 | /*====================================================================== | ||
770 | |||
771 | bind_request() and bind_device() are merged by now. Register_client() | ||
772 | is called right at the end of bind_request(), during the driver's | ||
773 | ->attach() call. Individual descriptions: | ||
774 | |||
775 | bind_request() connects a socket to a particular client driver. | ||
776 | It looks up the specified device ID in the list of registered | ||
777 | drivers, binds it to the socket, and tries to create an instance | ||
778 | of the device. unbind_request() deletes a driver instance. | ||
779 | |||
780 | Bind_device() associates a device driver with a particular socket. | ||
781 | It is normally called by Driver Services after it has identified | ||
782 | a newly inserted card. An instance of that driver will then be | ||
783 | eligible to register as a client of this socket. | ||
784 | |||
785 | Register_client() uses the dev_info_t handle to match the | ||
786 | caller with a socket. The driver must have already been bound | ||
787 | to a socket with bind_device() -- in fact, bind_device() | ||
788 | allocates the client structure that will be used. | ||
789 | |||
790 | ======================================================================*/ | ||
791 | |||
792 | static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) | ||
793 | { | ||
794 | struct pcmcia_driver *p_drv; | ||
795 | struct pcmcia_device *p_dev; | ||
796 | int ret = 0; | ||
797 | unsigned long flags; | ||
798 | |||
799 | s = pcmcia_get_bus_socket(s); | ||
800 | if (!s) | ||
801 | return -EINVAL; | ||
802 | |||
803 | ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock, | ||
804 | (char *)bind_info->dev_info); | ||
805 | |||
806 | p_drv = get_pcmcia_driver(&bind_info->dev_info); | ||
807 | if (!p_drv) { | ||
808 | ret = -EINVAL; | ||
809 | goto err_put; | ||
810 | } | ||
811 | |||
812 | if (!try_module_get(p_drv->owner)) { | ||
813 | ret = -EINVAL; | ||
814 | goto err_put_driver; | ||
815 | } | ||
816 | |||
817 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
818 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { | ||
819 | if (p_dev->func == bind_info->function) { | ||
820 | if ((p_dev->dev.driver == &p_drv->drv)) { | ||
821 | if (p_dev->cardmgr) { | ||
822 | /* if there's already a device | ||
823 | * registered, and it was registered | ||
824 | * by userspace before, we need to | ||
825 | * return the "instance". */ | ||
826 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
827 | bind_info->instance = p_dev->instance; | ||
828 | ret = -EBUSY; | ||
829 | goto err_put_module; | ||
830 | } else { | ||
831 | /* the correct driver managed to bind | ||
832 | * itself magically to the correct | ||
833 | * device. */ | ||
834 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
835 | p_dev->cardmgr = p_drv; | ||
836 | ret = 0; | ||
837 | goto err_put_module; | ||
838 | } | ||
839 | } else if (!p_dev->dev.driver) { | ||
840 | /* there's already a device available where | ||
841 | * no device has been bound to yet. So we don't | ||
842 | * need to register a device! */ | ||
843 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
844 | goto rescan; | ||
845 | } | ||
846 | } | ||
847 | } | ||
848 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
849 | |||
850 | p_dev = pcmcia_device_add(s, bind_info->function); | ||
851 | if (!p_dev) { | ||
852 | ret = -EIO; | ||
853 | goto err_put_module; | ||
854 | } | ||
855 | |||
856 | rescan: | ||
857 | p_dev->cardmgr = p_drv; | ||
858 | |||
859 | pcmcia_device_query(p_dev); | ||
860 | |||
861 | /* | ||
862 | * Prevent this racing with a card insertion. | ||
863 | */ | ||
864 | down(&s->parent->skt_sem); | ||
865 | bus_rescan_devices(&pcmcia_bus_type); | ||
866 | up(&s->parent->skt_sem); | ||
867 | |||
868 | /* check whether the driver indeed matched. I don't care if this | ||
869 | * is racy or not, because it can only happen on cardmgr access | ||
870 | * paths... | ||
871 | */ | ||
872 | if (!(p_dev->dev.driver == &p_drv->drv)) | ||
873 | p_dev->cardmgr = NULL; | ||
874 | |||
875 | err_put_module: | ||
876 | module_put(p_drv->owner); | ||
877 | err_put_driver: | ||
878 | put_driver(&p_drv->drv); | ||
879 | err_put: | ||
880 | pcmcia_put_bus_socket(s); | ||
881 | |||
882 | return (ret); | ||
883 | } /* bind_request */ | ||
884 | |||
885 | 989 | ||
886 | int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | 990 | int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) |
887 | { | 991 | { |
888 | client_t *client = NULL; | 992 | client_t *client = NULL; |
889 | struct pcmcia_socket *s; | 993 | struct pcmcia_socket *s = NULL; |
890 | struct pcmcia_bus_socket *skt = NULL; | ||
891 | struct pcmcia_device *p_dev = NULL; | 994 | struct pcmcia_device *p_dev = NULL; |
892 | 995 | ||
893 | /* Look for unbound client with matching dev_info */ | 996 | /* Look for unbound client with matching dev_info */ |
@@ -898,14 +1001,11 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
898 | if (s->state & SOCKET_CARDBUS) | 1001 | if (s->state & SOCKET_CARDBUS) |
899 | continue; | 1002 | continue; |
900 | 1003 | ||
901 | skt = s->pcmcia; | 1004 | s = pcmcia_get_socket(s); |
902 | if (!skt) | 1005 | if (!s) |
903 | continue; | ||
904 | skt = pcmcia_get_bus_socket(skt); | ||
905 | if (!skt) | ||
906 | continue; | 1006 | continue; |
907 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 1007 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
908 | list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) { | 1008 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { |
909 | struct pcmcia_driver *p_drv; | 1009 | struct pcmcia_driver *p_drv; |
910 | p_dev = pcmcia_get_dev(p_dev); | 1010 | p_dev = pcmcia_get_dev(p_dev); |
911 | if (!p_dev) | 1011 | if (!p_dev) |
@@ -924,14 +1024,14 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
924 | pcmcia_put_dev(p_dev); | 1024 | pcmcia_put_dev(p_dev); |
925 | } | 1025 | } |
926 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 1026 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
927 | pcmcia_put_bus_socket(skt); | 1027 | pcmcia_put_socket(s); |
928 | } | 1028 | } |
929 | found: | 1029 | found: |
930 | up_read(&pcmcia_socket_list_rwsem); | 1030 | up_read(&pcmcia_socket_list_rwsem); |
931 | if (!p_dev || !client) | 1031 | if (!p_dev || !client) |
932 | return -ENODEV; | 1032 | return -ENODEV; |
933 | 1033 | ||
934 | pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */ | 1034 | pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */ |
935 | 1035 | ||
936 | *handle = client; | 1036 | *handle = client; |
937 | client->state &= ~CLIENT_UNBOUND; | 1037 | client->state &= ~CLIENT_UNBOUND; |
@@ -978,106 +1078,15 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) | |||
978 | EXPORT_SYMBOL(pcmcia_register_client); | 1078 | EXPORT_SYMBOL(pcmcia_register_client); |
979 | 1079 | ||
980 | 1080 | ||
981 | /*====================================================================*/ | ||
982 | |||
983 | extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s); | ||
984 | |||
985 | static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first) | ||
986 | { | ||
987 | dev_node_t *node; | ||
988 | struct pcmcia_device *p_dev; | ||
989 | unsigned long flags; | ||
990 | int ret = 0; | ||
991 | |||
992 | #ifdef CONFIG_CARDBUS | ||
993 | /* | ||
994 | * Some unbelievably ugly code to associate the PCI cardbus | ||
995 | * device and its driver with the PCMCIA "bind" information. | ||
996 | */ | ||
997 | { | ||
998 | struct pci_bus *bus; | ||
999 | |||
1000 | bus = pcmcia_lookup_bus(s->parent); | ||
1001 | if (bus) { | ||
1002 | struct list_head *list; | ||
1003 | struct pci_dev *dev = NULL; | ||
1004 | |||
1005 | list = bus->devices.next; | ||
1006 | while (list != &bus->devices) { | ||
1007 | struct pci_dev *pdev = pci_dev_b(list); | ||
1008 | list = list->next; | ||
1009 | |||
1010 | if (first) { | ||
1011 | dev = pdev; | ||
1012 | break; | ||
1013 | } | ||
1014 | |||
1015 | /* Try to handle "next" here some way? */ | ||
1016 | } | ||
1017 | if (dev && dev->driver) { | ||
1018 | strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN); | ||
1019 | bind_info->major = 0; | ||
1020 | bind_info->minor = 0; | ||
1021 | bind_info->next = NULL; | ||
1022 | return 0; | ||
1023 | } | ||
1024 | } | ||
1025 | } | ||
1026 | #endif | ||
1027 | |||
1028 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
1029 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { | ||
1030 | if (p_dev->func == bind_info->function) { | ||
1031 | p_dev = pcmcia_get_dev(p_dev); | ||
1032 | if (!p_dev) | ||
1033 | continue; | ||
1034 | goto found; | ||
1035 | } | ||
1036 | } | ||
1037 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
1038 | return -ENODEV; | ||
1039 | |||
1040 | found: | ||
1041 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
1042 | |||
1043 | if ((!p_dev->instance) || | ||
1044 | (p_dev->instance->state & DEV_CONFIG_PENDING)) { | ||
1045 | ret = -EAGAIN; | ||
1046 | goto err_put; | ||
1047 | } | ||
1048 | |||
1049 | if (first) | ||
1050 | node = p_dev->instance->dev; | ||
1051 | else | ||
1052 | for (node = p_dev->instance->dev; node; node = node->next) | ||
1053 | if (node == bind_info->next) | ||
1054 | break; | ||
1055 | if (!node) { | ||
1056 | ret = -ENODEV; | ||
1057 | goto err_put; | ||
1058 | } | ||
1059 | |||
1060 | strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); | ||
1061 | bind_info->major = node->major; | ||
1062 | bind_info->minor = node->minor; | ||
1063 | bind_info->next = node->next; | ||
1064 | |||
1065 | err_put: | ||
1066 | pcmcia_put_dev(p_dev); | ||
1067 | return (ret); | ||
1068 | } /* get_device_info */ | ||
1069 | |||
1070 | /*====================================================================*/ | ||
1071 | |||
1072 | /* unbind _all_ devices attached to a given pcmcia_bus_socket. The | 1081 | /* unbind _all_ devices attached to a given pcmcia_bus_socket. The |
1073 | * drivers have been called with EVENT_CARD_REMOVAL before. | 1082 | * drivers have been called with EVENT_CARD_REMOVAL before. |
1074 | */ | 1083 | */ |
1075 | static int unbind_request(struct pcmcia_bus_socket *s) | 1084 | static int unbind_request(struct pcmcia_socket *s) |
1076 | { | 1085 | { |
1077 | struct pcmcia_device *p_dev; | 1086 | struct pcmcia_device *p_dev; |
1078 | unsigned long flags; | 1087 | unsigned long flags; |
1079 | 1088 | ||
1080 | ds_dbg(2, "unbind_request(%d)\n", s->parent->sock); | 1089 | ds_dbg(2, "unbind_request(%d)\n", s->sock); |
1081 | 1090 | ||
1082 | s->device_count = 0; | 1091 | s->device_count = 0; |
1083 | 1092 | ||
@@ -1133,433 +1142,58 @@ int pcmcia_deregister_client(client_handle_t handle) | |||
1133 | } /* deregister_client */ | 1142 | } /* deregister_client */ |
1134 | EXPORT_SYMBOL(pcmcia_deregister_client); | 1143 | EXPORT_SYMBOL(pcmcia_deregister_client); |
1135 | 1144 | ||
1136 | 1145 | static struct pcmcia_callback pcmcia_bus_callback = { | |
1137 | /*====================================================================== | 1146 | .owner = THIS_MODULE, |
1138 | 1147 | .event = ds_event, | |
1139 | The user-mode PC Card device interface | 1148 | .requery = pcmcia_bus_rescan, |
1140 | |||
1141 | ======================================================================*/ | ||
1142 | |||
1143 | static int ds_open(struct inode *inode, struct file *file) | ||
1144 | { | ||
1145 | socket_t i = iminor(inode); | ||
1146 | struct pcmcia_bus_socket *s; | ||
1147 | user_info_t *user; | ||
1148 | |||
1149 | ds_dbg(0, "ds_open(socket %d)\n", i); | ||
1150 | |||
1151 | s = get_socket_info_by_nr(i); | ||
1152 | if (!s) | ||
1153 | return -ENODEV; | ||
1154 | s = pcmcia_get_bus_socket(s); | ||
1155 | if (!s) | ||
1156 | return -ENODEV; | ||
1157 | |||
1158 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
1159 | if (s->state & DS_SOCKET_BUSY) { | ||
1160 | pcmcia_put_bus_socket(s); | ||
1161 | return -EBUSY; | ||
1162 | } | ||
1163 | else | ||
1164 | s->state |= DS_SOCKET_BUSY; | ||
1165 | } | ||
1166 | |||
1167 | user = kmalloc(sizeof(user_info_t), GFP_KERNEL); | ||
1168 | if (!user) { | ||
1169 | pcmcia_put_bus_socket(s); | ||
1170 | return -ENOMEM; | ||
1171 | } | ||
1172 | user->event_tail = user->event_head = 0; | ||
1173 | user->next = s->user; | ||
1174 | user->user_magic = USER_MAGIC; | ||
1175 | user->socket = s; | ||
1176 | s->user = user; | ||
1177 | file->private_data = user; | ||
1178 | |||
1179 | if (s->state & DS_SOCKET_PRESENT) | ||
1180 | queue_event(user, CS_EVENT_CARD_INSERTION); | ||
1181 | return 0; | ||
1182 | } /* ds_open */ | ||
1183 | |||
1184 | /*====================================================================*/ | ||
1185 | |||
1186 | static int ds_release(struct inode *inode, struct file *file) | ||
1187 | { | ||
1188 | struct pcmcia_bus_socket *s; | ||
1189 | user_info_t *user, **link; | ||
1190 | |||
1191 | ds_dbg(0, "ds_release(socket %d)\n", iminor(inode)); | ||
1192 | |||
1193 | user = file->private_data; | ||
1194 | if (CHECK_USER(user)) | ||
1195 | goto out; | ||
1196 | |||
1197 | s = user->socket; | ||
1198 | |||
1199 | /* Unlink user data structure */ | ||
1200 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
1201 | s->state &= ~DS_SOCKET_BUSY; | ||
1202 | } | ||
1203 | file->private_data = NULL; | ||
1204 | for (link = &s->user; *link; link = &(*link)->next) | ||
1205 | if (*link == user) break; | ||
1206 | if (link == NULL) | ||
1207 | goto out; | ||
1208 | *link = user->next; | ||
1209 | user->user_magic = 0; | ||
1210 | kfree(user); | ||
1211 | pcmcia_put_bus_socket(s); | ||
1212 | out: | ||
1213 | return 0; | ||
1214 | } /* ds_release */ | ||
1215 | |||
1216 | /*====================================================================*/ | ||
1217 | |||
1218 | static ssize_t ds_read(struct file *file, char __user *buf, | ||
1219 | size_t count, loff_t *ppos) | ||
1220 | { | ||
1221 | struct pcmcia_bus_socket *s; | ||
1222 | user_info_t *user; | ||
1223 | int ret; | ||
1224 | |||
1225 | ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode)); | ||
1226 | |||
1227 | if (count < 4) | ||
1228 | return -EINVAL; | ||
1229 | |||
1230 | user = file->private_data; | ||
1231 | if (CHECK_USER(user)) | ||
1232 | return -EIO; | ||
1233 | |||
1234 | s = user->socket; | ||
1235 | if (s->state & DS_SOCKET_DEAD) | ||
1236 | return -EIO; | ||
1237 | |||
1238 | ret = wait_event_interruptible(s->queue, !queue_empty(user)); | ||
1239 | if (ret == 0) | ||
1240 | ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; | ||
1241 | |||
1242 | return ret; | ||
1243 | } /* ds_read */ | ||
1244 | |||
1245 | /*====================================================================*/ | ||
1246 | |||
1247 | static ssize_t ds_write(struct file *file, const char __user *buf, | ||
1248 | size_t count, loff_t *ppos) | ||
1249 | { | ||
1250 | ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode)); | ||
1251 | |||
1252 | if (count != 4) | ||
1253 | return -EINVAL; | ||
1254 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | ||
1255 | return -EBADF; | ||
1256 | |||
1257 | return -EIO; | ||
1258 | } /* ds_write */ | ||
1259 | |||
1260 | /*====================================================================*/ | ||
1261 | |||
1262 | /* No kernel lock - fine */ | ||
1263 | static u_int ds_poll(struct file *file, poll_table *wait) | ||
1264 | { | ||
1265 | struct pcmcia_bus_socket *s; | ||
1266 | user_info_t *user; | ||
1267 | |||
1268 | ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode)); | ||
1269 | |||
1270 | user = file->private_data; | ||
1271 | if (CHECK_USER(user)) | ||
1272 | return POLLERR; | ||
1273 | s = user->socket; | ||
1274 | /* | ||
1275 | * We don't check for a dead socket here since that | ||
1276 | * will send cardmgr into an endless spin. | ||
1277 | */ | ||
1278 | poll_wait(file, &s->queue, wait); | ||
1279 | if (!queue_empty(user)) | ||
1280 | return POLLIN | POLLRDNORM; | ||
1281 | return 0; | ||
1282 | } /* ds_poll */ | ||
1283 | |||
1284 | /*====================================================================*/ | ||
1285 | |||
1286 | extern int pcmcia_adjust_resource_info(adjust_t *adj); | ||
1287 | |||
1288 | static int ds_ioctl(struct inode * inode, struct file * file, | ||
1289 | u_int cmd, u_long arg) | ||
1290 | { | ||
1291 | struct pcmcia_bus_socket *s; | ||
1292 | void __user *uarg = (char __user *)arg; | ||
1293 | u_int size; | ||
1294 | int ret, err; | ||
1295 | ds_ioctl_arg_t *buf; | ||
1296 | user_info_t *user; | ||
1297 | |||
1298 | ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg); | ||
1299 | |||
1300 | user = file->private_data; | ||
1301 | if (CHECK_USER(user)) | ||
1302 | return -EIO; | ||
1303 | |||
1304 | s = user->socket; | ||
1305 | if (s->state & DS_SOCKET_DEAD) | ||
1306 | return -EIO; | ||
1307 | |||
1308 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; | ||
1309 | if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; | ||
1310 | |||
1311 | /* Permission check */ | ||
1312 | if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN)) | ||
1313 | return -EPERM; | ||
1314 | |||
1315 | if (cmd & IOC_IN) { | ||
1316 | if (!access_ok(VERIFY_READ, uarg, size)) { | ||
1317 | ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT); | ||
1318 | return -EFAULT; | ||
1319 | } | ||
1320 | } | ||
1321 | if (cmd & IOC_OUT) { | ||
1322 | if (!access_ok(VERIFY_WRITE, uarg, size)) { | ||
1323 | ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT); | ||
1324 | return -EFAULT; | ||
1325 | } | ||
1326 | } | ||
1327 | buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL); | ||
1328 | if (!buf) | ||
1329 | return -ENOMEM; | ||
1330 | |||
1331 | err = ret = 0; | ||
1332 | |||
1333 | if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size); | ||
1334 | |||
1335 | switch (cmd) { | ||
1336 | case DS_ADJUST_RESOURCE_INFO: | ||
1337 | ret = pcmcia_adjust_resource_info(&buf->adjust); | ||
1338 | break; | ||
1339 | case DS_GET_CARD_SERVICES_INFO: | ||
1340 | ret = pcmcia_get_card_services_info(&buf->servinfo); | ||
1341 | break; | ||
1342 | case DS_GET_CONFIGURATION_INFO: | ||
1343 | if (buf->config.Function && | ||
1344 | (buf->config.Function >= s->parent->functions)) | ||
1345 | ret = CS_BAD_ARGS; | ||
1346 | else | ||
1347 | ret = pccard_get_configuration_info(s->parent, | ||
1348 | buf->config.Function, &buf->config); | ||
1349 | break; | ||
1350 | case DS_GET_FIRST_TUPLE: | ||
1351 | down(&s->parent->skt_sem); | ||
1352 | pcmcia_validate_mem(s->parent); | ||
1353 | up(&s->parent->skt_sem); | ||
1354 | ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf->tuple); | ||
1355 | break; | ||
1356 | case DS_GET_NEXT_TUPLE: | ||
1357 | ret = pccard_get_next_tuple(s->parent, BIND_FN_ALL, &buf->tuple); | ||
1358 | break; | ||
1359 | case DS_GET_TUPLE_DATA: | ||
1360 | buf->tuple.TupleData = buf->tuple_parse.data; | ||
1361 | buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data); | ||
1362 | ret = pccard_get_tuple_data(s->parent, &buf->tuple); | ||
1363 | break; | ||
1364 | case DS_PARSE_TUPLE: | ||
1365 | buf->tuple.TupleData = buf->tuple_parse.data; | ||
1366 | ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse); | ||
1367 | break; | ||
1368 | case DS_RESET_CARD: | ||
1369 | ret = pccard_reset_card(s->parent); | ||
1370 | break; | ||
1371 | case DS_GET_STATUS: | ||
1372 | if (buf->status.Function && | ||
1373 | (buf->status.Function >= s->parent->functions)) | ||
1374 | ret = CS_BAD_ARGS; | ||
1375 | else | ||
1376 | ret = pccard_get_status(s->parent, buf->status.Function, &buf->status); | ||
1377 | break; | ||
1378 | case DS_VALIDATE_CIS: | ||
1379 | down(&s->parent->skt_sem); | ||
1380 | pcmcia_validate_mem(s->parent); | ||
1381 | up(&s->parent->skt_sem); | ||
1382 | ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf->cisinfo); | ||
1383 | break; | ||
1384 | case DS_SUSPEND_CARD: | ||
1385 | ret = pcmcia_suspend_card(s->parent); | ||
1386 | break; | ||
1387 | case DS_RESUME_CARD: | ||
1388 | ret = pcmcia_resume_card(s->parent); | ||
1389 | break; | ||
1390 | case DS_EJECT_CARD: | ||
1391 | err = pcmcia_eject_card(s->parent); | ||
1392 | break; | ||
1393 | case DS_INSERT_CARD: | ||
1394 | err = pcmcia_insert_card(s->parent); | ||
1395 | break; | ||
1396 | case DS_ACCESS_CONFIGURATION_REGISTER: | ||
1397 | if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) { | ||
1398 | err = -EPERM; | ||
1399 | goto free_out; | ||
1400 | } | ||
1401 | if (buf->conf_reg.Function && | ||
1402 | (buf->conf_reg.Function >= s->parent->functions)) | ||
1403 | ret = CS_BAD_ARGS; | ||
1404 | else | ||
1405 | ret = pccard_access_configuration_register(s->parent, | ||
1406 | buf->conf_reg.Function, &buf->conf_reg); | ||
1407 | break; | ||
1408 | case DS_GET_FIRST_REGION: | ||
1409 | case DS_GET_NEXT_REGION: | ||
1410 | case DS_BIND_MTD: | ||
1411 | if (!capable(CAP_SYS_ADMIN)) { | ||
1412 | err = -EPERM; | ||
1413 | goto free_out; | ||
1414 | } else { | ||
1415 | static int printed = 0; | ||
1416 | if (!printed) { | ||
1417 | printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n"); | ||
1418 | printk(KERN_WARNING "MTD handling any more.\n"); | ||
1419 | printed++; | ||
1420 | } | ||
1421 | } | ||
1422 | err = -EINVAL; | ||
1423 | goto free_out; | ||
1424 | break; | ||
1425 | case DS_GET_FIRST_WINDOW: | ||
1426 | ret = pcmcia_get_window(s->parent, &buf->win_info.handle, 0, | ||
1427 | &buf->win_info.window); | ||
1428 | break; | ||
1429 | case DS_GET_NEXT_WINDOW: | ||
1430 | ret = pcmcia_get_window(s->parent, &buf->win_info.handle, | ||
1431 | buf->win_info.handle->index + 1, &buf->win_info.window); | ||
1432 | break; | ||
1433 | case DS_GET_MEM_PAGE: | ||
1434 | ret = pcmcia_get_mem_page(buf->win_info.handle, | ||
1435 | &buf->win_info.map); | ||
1436 | break; | ||
1437 | case DS_REPLACE_CIS: | ||
1438 | ret = pcmcia_replace_cis(s->parent, &buf->cisdump); | ||
1439 | break; | ||
1440 | case DS_BIND_REQUEST: | ||
1441 | if (!capable(CAP_SYS_ADMIN)) { | ||
1442 | err = -EPERM; | ||
1443 | goto free_out; | ||
1444 | } | ||
1445 | err = bind_request(s, &buf->bind_info); | ||
1446 | break; | ||
1447 | case DS_GET_DEVICE_INFO: | ||
1448 | err = get_device_info(s, &buf->bind_info, 1); | ||
1449 | break; | ||
1450 | case DS_GET_NEXT_DEVICE: | ||
1451 | err = get_device_info(s, &buf->bind_info, 0); | ||
1452 | break; | ||
1453 | case DS_UNBIND_REQUEST: | ||
1454 | err = 0; | ||
1455 | break; | ||
1456 | default: | ||
1457 | err = -EINVAL; | ||
1458 | } | ||
1459 | |||
1460 | if ((err == 0) && (ret != CS_SUCCESS)) { | ||
1461 | ds_dbg(2, "ds_ioctl: ret = %d\n", ret); | ||
1462 | switch (ret) { | ||
1463 | case CS_BAD_SOCKET: case CS_NO_CARD: | ||
1464 | err = -ENODEV; break; | ||
1465 | case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ: | ||
1466 | case CS_BAD_TUPLE: | ||
1467 | err = -EINVAL; break; | ||
1468 | case CS_IN_USE: | ||
1469 | err = -EBUSY; break; | ||
1470 | case CS_OUT_OF_RESOURCE: | ||
1471 | err = -ENOSPC; break; | ||
1472 | case CS_NO_MORE_ITEMS: | ||
1473 | err = -ENODATA; break; | ||
1474 | case CS_UNSUPPORTED_FUNCTION: | ||
1475 | err = -ENOSYS; break; | ||
1476 | default: | ||
1477 | err = -EIO; break; | ||
1478 | } | ||
1479 | } | ||
1480 | |||
1481 | if (cmd & IOC_OUT) { | ||
1482 | if (__copy_to_user(uarg, (char *)buf, size)) | ||
1483 | err = -EFAULT; | ||
1484 | } | ||
1485 | |||
1486 | free_out: | ||
1487 | kfree(buf); | ||
1488 | return err; | ||
1489 | } /* ds_ioctl */ | ||
1490 | |||
1491 | /*====================================================================*/ | ||
1492 | |||
1493 | static struct file_operations ds_fops = { | ||
1494 | .owner = THIS_MODULE, | ||
1495 | .open = ds_open, | ||
1496 | .release = ds_release, | ||
1497 | .ioctl = ds_ioctl, | ||
1498 | .read = ds_read, | ||
1499 | .write = ds_write, | ||
1500 | .poll = ds_poll, | ||
1501 | }; | 1149 | }; |
1502 | 1150 | ||
1503 | static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) | 1151 | static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) |
1504 | { | 1152 | { |
1505 | struct pcmcia_socket *socket = class_get_devdata(class_dev); | 1153 | struct pcmcia_socket *socket = class_get_devdata(class_dev); |
1506 | struct pcmcia_bus_socket *s; | ||
1507 | int ret; | 1154 | int ret; |
1508 | 1155 | ||
1509 | s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL); | 1156 | socket = pcmcia_get_socket(socket); |
1510 | if(!s) | 1157 | if (!socket) { |
1511 | return -ENOMEM; | ||
1512 | memset(s, 0, sizeof(struct pcmcia_bus_socket)); | ||
1513 | |||
1514 | /* get reference to parent socket */ | ||
1515 | s->parent = pcmcia_get_socket(socket); | ||
1516 | if (!s->parent) { | ||
1517 | printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket); | 1158 | printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket); |
1518 | kfree (s); | ||
1519 | return -ENODEV; | 1159 | return -ENODEV; |
1520 | } | 1160 | } |
1521 | 1161 | ||
1522 | kref_init(&s->refcount); | ||
1523 | |||
1524 | /* | 1162 | /* |
1525 | * Ugly. But we want to wait for the socket threads to have started up. | 1163 | * Ugly. But we want to wait for the socket threads to have started up. |
1526 | * We really should let the drivers themselves drive some of this.. | 1164 | * We really should let the drivers themselves drive some of this.. |
1527 | */ | 1165 | */ |
1528 | msleep(250); | 1166 | msleep(250); |
1529 | 1167 | ||
1530 | init_waitqueue_head(&s->queue); | 1168 | #ifdef CONFIG_PCMCIA_IOCTL |
1531 | INIT_LIST_HEAD(&s->devices_list); | 1169 | init_waitqueue_head(&socket->queue); |
1532 | 1170 | #endif | |
1533 | /* Set up hotline to Card Services */ | 1171 | INIT_LIST_HEAD(&socket->devices_list); |
1534 | s->callback.owner = THIS_MODULE; | 1172 | INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device, socket); |
1535 | s->callback.event = &ds_event; | 1173 | memset(&socket->pcmcia_state, 0, sizeof(u8)); |
1536 | s->callback.resources_done = &pcmcia_card_add; | 1174 | socket->device_count = 0; |
1537 | socket->pcmcia = s; | ||
1538 | 1175 | ||
1539 | ret = pccard_register_pcmcia(socket, &s->callback); | 1176 | ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback); |
1540 | if (ret) { | 1177 | if (ret) { |
1541 | printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket); | 1178 | printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket); |
1542 | pcmcia_put_bus_socket(s); | 1179 | pcmcia_put_socket(socket); |
1543 | socket->pcmcia = NULL; | ||
1544 | return (ret); | 1180 | return (ret); |
1545 | } | 1181 | } |
1546 | 1182 | ||
1547 | return 0; | 1183 | return 0; |
1548 | } | 1184 | } |
1549 | 1185 | ||
1550 | |||
1551 | static void pcmcia_bus_remove_socket(struct class_device *class_dev) | 1186 | static void pcmcia_bus_remove_socket(struct class_device *class_dev) |
1552 | { | 1187 | { |
1553 | struct pcmcia_socket *socket = class_get_devdata(class_dev); | 1188 | struct pcmcia_socket *socket = class_get_devdata(class_dev); |
1554 | 1189 | ||
1555 | if (!socket || !socket->pcmcia) | 1190 | if (!socket) |
1556 | return; | 1191 | return; |
1557 | 1192 | ||
1193 | socket->pcmcia_state.dead = 1; | ||
1558 | pccard_register_pcmcia(socket, NULL); | 1194 | pccard_register_pcmcia(socket, NULL); |
1559 | 1195 | ||
1560 | socket->pcmcia->state |= DS_SOCKET_DEAD; | 1196 | pcmcia_put_socket(socket); |
1561 | pcmcia_put_bus_socket(socket->pcmcia); | ||
1562 | socket->pcmcia = NULL; | ||
1563 | 1197 | ||
1564 | return; | 1198 | return; |
1565 | } | 1199 | } |
@@ -1575,34 +1209,20 @@ static struct class_interface pcmcia_bus_interface = { | |||
1575 | 1209 | ||
1576 | struct bus_type pcmcia_bus_type = { | 1210 | struct bus_type pcmcia_bus_type = { |
1577 | .name = "pcmcia", | 1211 | .name = "pcmcia", |
1212 | .hotplug = pcmcia_bus_hotplug, | ||
1578 | .match = pcmcia_bus_match, | 1213 | .match = pcmcia_bus_match, |
1579 | .dev_attrs = pcmcia_dev_attrs, | 1214 | .dev_attrs = pcmcia_dev_attrs, |
1580 | }; | 1215 | }; |
1581 | EXPORT_SYMBOL(pcmcia_bus_type); | ||
1582 | 1216 | ||
1583 | 1217 | ||
1584 | static int __init init_pcmcia_bus(void) | 1218 | static int __init init_pcmcia_bus(void) |
1585 | { | 1219 | { |
1586 | int i; | ||
1587 | |||
1588 | spin_lock_init(&pcmcia_dev_list_lock); | 1220 | spin_lock_init(&pcmcia_dev_list_lock); |
1589 | 1221 | ||
1590 | bus_register(&pcmcia_bus_type); | 1222 | bus_register(&pcmcia_bus_type); |
1591 | class_interface_register(&pcmcia_bus_interface); | 1223 | class_interface_register(&pcmcia_bus_interface); |
1592 | 1224 | ||
1593 | /* Set up character device for user mode clients */ | 1225 | pcmcia_setup_ioctl(); |
1594 | i = register_chrdev(0, "pcmcia", &ds_fops); | ||
1595 | if (i < 0) | ||
1596 | printk(KERN_NOTICE "unable to find a free device # for " | ||
1597 | "Driver Services (error=%d)\n", i); | ||
1598 | else | ||
1599 | major_dev = i; | ||
1600 | |||
1601 | #ifdef CONFIG_PROC_FS | ||
1602 | proc_pccard = proc_mkdir("pccard", proc_bus); | ||
1603 | if (proc_pccard) | ||
1604 | create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL); | ||
1605 | #endif | ||
1606 | 1226 | ||
1607 | return 0; | 1227 | return 0; |
1608 | } | 1228 | } |
@@ -1612,48 +1232,13 @@ fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that | |||
1612 | 1232 | ||
1613 | static void __exit exit_pcmcia_bus(void) | 1233 | static void __exit exit_pcmcia_bus(void) |
1614 | { | 1234 | { |
1615 | class_interface_unregister(&pcmcia_bus_interface); | 1235 | pcmcia_cleanup_ioctl(); |
1616 | 1236 | ||
1617 | #ifdef CONFIG_PROC_FS | 1237 | class_interface_unregister(&pcmcia_bus_interface); |
1618 | if (proc_pccard) { | ||
1619 | remove_proc_entry("drivers", proc_pccard); | ||
1620 | remove_proc_entry("pccard", proc_bus); | ||
1621 | } | ||
1622 | #endif | ||
1623 | if (major_dev != -1) | ||
1624 | unregister_chrdev(major_dev, "pcmcia"); | ||
1625 | 1238 | ||
1626 | bus_unregister(&pcmcia_bus_type); | 1239 | bus_unregister(&pcmcia_bus_type); |
1627 | } | 1240 | } |
1628 | module_exit(exit_pcmcia_bus); | 1241 | module_exit(exit_pcmcia_bus); |
1629 | 1242 | ||
1630 | 1243 | ||
1631 | |||
1632 | /* helpers for backwards-compatible functions */ | ||
1633 | |||
1634 | static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr) | ||
1635 | { | ||
1636 | struct pcmcia_socket * s = pcmcia_get_socket_by_nr(nr); | ||
1637 | if (s && s->pcmcia) | ||
1638 | return s->pcmcia; | ||
1639 | else | ||
1640 | return NULL; | ||
1641 | } | ||
1642 | |||
1643 | /* backwards-compatible accessing of driver --- by name! */ | ||
1644 | |||
1645 | static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) | ||
1646 | { | ||
1647 | struct device_driver *drv; | ||
1648 | struct pcmcia_driver *p_drv; | ||
1649 | |||
1650 | drv = driver_find((char *) dev_info, &pcmcia_bus_type); | ||
1651 | if (!drv) | ||
1652 | return NULL; | ||
1653 | |||
1654 | p_drv = container_of(drv, struct pcmcia_driver, drv); | ||
1655 | |||
1656 | return (p_drv); | ||
1657 | } | ||
1658 | |||
1659 | MODULE_ALIAS("ds"); | 1244 | MODULE_ALIAS("ds"); |
diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h new file mode 100644 index 000000000000..d359bd25a51c --- /dev/null +++ b/drivers/pcmcia/ds_internal.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* ds_internal.h - internal header for 16-bit PCMCIA devices management */ | ||
2 | |||
3 | extern spinlock_t pcmcia_dev_list_lock; | ||
4 | extern struct bus_type pcmcia_bus_type; | ||
5 | |||
6 | extern struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev); | ||
7 | extern void pcmcia_put_dev(struct pcmcia_device *p_dev); | ||
8 | |||
9 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function); | ||
10 | |||
11 | #ifdef CONFIG_PCMCIA_IOCTL | ||
12 | extern void __init pcmcia_setup_ioctl(void); | ||
13 | extern void __exit pcmcia_cleanup_ioctl(void); | ||
14 | extern void handle_event(struct pcmcia_socket *s, event_t event); | ||
15 | extern int handle_request(struct pcmcia_socket *s, event_t event); | ||
16 | #else | ||
17 | static inline void __init pcmcia_setup_ioctl(void) { return; } | ||
18 | static inline void __init pcmcia_cleanup_ioctl(void) { return; } | ||
19 | static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; } | ||
20 | static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; } | ||
21 | #endif | ||
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 90a335a5d9fa..d72f9a35c8bd 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
@@ -669,11 +669,13 @@ static int __init is_alive(u_short sock) | |||
669 | if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) && | 669 | if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) && |
670 | (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) && | 670 | (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) && |
671 | (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) && | 671 | (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) && |
672 | (check_region(start, stop-start+1) != 0) && | 672 | ((start & 0xfeef) != 0x02e8)) { |
673 | ((start & 0xfeef) != 0x02e8)) | 673 | if (!request_region(start, stop-start+1, "i82365")) |
674 | return 1; | 674 | return 1; |
675 | else | 675 | release_region(start, stop-start+1); |
676 | return 0; | 676 | } |
677 | |||
678 | return 0; | ||
677 | } | 679 | } |
678 | 680 | ||
679 | /*====================================================================*/ | 681 | /*====================================================================*/ |
@@ -696,7 +698,13 @@ static void __init add_pcic(int ns, int type) | |||
696 | struct i82365_socket *t = &socket[sockets-ns]; | 698 | struct i82365_socket *t = &socket[sockets-ns]; |
697 | 699 | ||
698 | base = sockets-ns; | 700 | base = sockets-ns; |
699 | if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365"); | 701 | if (t->ioaddr > 0) { |
702 | if (!request_region(t->ioaddr, 2, "i82365")) { | ||
703 | printk(KERN_ERR "i82365: IO region conflict at %#lx, not available\n", | ||
704 | t->ioaddr); | ||
705 | return; | ||
706 | } | ||
707 | } | ||
700 | 708 | ||
701 | if (base == 0) printk("\n"); | 709 | if (base == 0) printk("\n"); |
702 | printk(KERN_INFO " %s", pcic[type].name); | 710 | printk(KERN_INFO " %s", pcic[type].name); |
@@ -803,7 +811,7 @@ static void __init isa_probe(void) | |||
803 | } | 811 | } |
804 | #endif | 812 | #endif |
805 | 813 | ||
806 | if (check_region(i365_base, 2) != 0) { | 814 | if (!request_region(i365_base, 2, "i82365")) { |
807 | if (sockets == 0) | 815 | if (sockets == 0) |
808 | printk("port conflict at %#lx\n", i365_base); | 816 | printk("port conflict at %#lx\n", i365_base); |
809 | return; | 817 | return; |
@@ -1441,6 +1449,7 @@ static void __exit exit_i82365(void) | |||
1441 | i365_set(i, I365_CSCINT, 0); | 1449 | i365_set(i, I365_CSCINT, 0); |
1442 | release_region(socket[i].ioaddr, 2); | 1450 | release_region(socket[i].ioaddr, 2); |
1443 | } | 1451 | } |
1452 | release_region(i365_base, 2); | ||
1444 | #ifdef CONFIG_PNP | 1453 | #ifdef CONFIG_PNP |
1445 | if (i82365_pnpdev) | 1454 | if (i82365_pnpdev) |
1446 | pnp_disable_dev(i82365_pnpdev); | 1455 | pnp_disable_dev(i82365_pnpdev); |
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c index 68b80084f83f..1cc83317e7e3 100644 --- a/drivers/pcmcia/pcmcia_compat.c +++ b/drivers/pcmcia/pcmcia_compat.c | |||
@@ -74,19 +74,6 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) | |||
74 | } | 74 | } |
75 | EXPORT_SYMBOL(pcmcia_validate_cis); | 75 | EXPORT_SYMBOL(pcmcia_validate_cis); |
76 | 76 | ||
77 | int pcmcia_get_configuration_info(client_handle_t handle, | ||
78 | config_info_t *config) | ||
79 | { | ||
80 | struct pcmcia_socket *s; | ||
81 | |||
82 | if ((CHECK_HANDLE(handle)) || !config) | ||
83 | return CS_BAD_HANDLE; | ||
84 | s = SOCKET(handle); | ||
85 | if (!s) | ||
86 | return CS_BAD_HANDLE; | ||
87 | return pccard_get_configuration_info(s, handle->Function, config); | ||
88 | } | ||
89 | EXPORT_SYMBOL(pcmcia_get_configuration_info); | ||
90 | 77 | ||
91 | int pcmcia_reset_card(client_handle_t handle, client_req_t *req) | 78 | int pcmcia_reset_card(client_handle_t handle, client_req_t *req) |
92 | { | 79 | { |
@@ -102,24 +89,3 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req) | |||
102 | } | 89 | } |
103 | EXPORT_SYMBOL(pcmcia_reset_card); | 90 | EXPORT_SYMBOL(pcmcia_reset_card); |
104 | 91 | ||
105 | int pcmcia_get_status(client_handle_t handle, cs_status_t *status) | ||
106 | { | ||
107 | struct pcmcia_socket *s; | ||
108 | if (CHECK_HANDLE(handle)) | ||
109 | return CS_BAD_HANDLE; | ||
110 | s = SOCKET(handle); | ||
111 | return pccard_get_status(s, handle->Function, status); | ||
112 | } | ||
113 | EXPORT_SYMBOL(pcmcia_get_status); | ||
114 | |||
115 | int pcmcia_access_configuration_register(client_handle_t handle, | ||
116 | conf_reg_t *reg) | ||
117 | { | ||
118 | struct pcmcia_socket *s; | ||
119 | if (CHECK_HANDLE(handle)) | ||
120 | return CS_BAD_HANDLE; | ||
121 | s = SOCKET(handle); | ||
122 | return pccard_access_configuration_register(s, handle->Function, reg); | ||
123 | } | ||
124 | EXPORT_SYMBOL(pcmcia_access_configuration_register); | ||
125 | |||
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c new file mode 100644 index 000000000000..b883bc151ed0 --- /dev/null +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
@@ -0,0 +1,786 @@ | |||
1 | /* | ||
2 | * pcmcia_ioctl.c -- ioctl interface for cardmgr and cardctl | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * The initial developer of the original code is David A. Hinds | ||
9 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
11 | * | ||
12 | * (C) 1999 David A. Hinds | ||
13 | * (C) 2003 - 2004 Dominik Brodowski | ||
14 | */ | ||
15 | |||
16 | /* | ||
17 | * This file will go away soon. | ||
18 | */ | ||
19 | |||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/ioctl.h> | ||
28 | #include <linux/proc_fs.h> | ||
29 | #include <linux/poll.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/workqueue.h> | ||
32 | |||
33 | #define IN_CARD_SERVICES | ||
34 | #include <pcmcia/version.h> | ||
35 | #include <pcmcia/cs_types.h> | ||
36 | #include <pcmcia/cs.h> | ||
37 | #include <pcmcia/cistpl.h> | ||
38 | #include <pcmcia/ds.h> | ||
39 | #include <pcmcia/ss.h> | ||
40 | |||
41 | #include "cs_internal.h" | ||
42 | #include "ds_internal.h" | ||
43 | |||
44 | static int major_dev = -1; | ||
45 | |||
46 | |||
47 | /* Device user information */ | ||
48 | #define MAX_EVENTS 32 | ||
49 | #define USER_MAGIC 0x7ea4 | ||
50 | #define CHECK_USER(u) \ | ||
51 | (((u) == NULL) || ((u)->user_magic != USER_MAGIC)) | ||
52 | |||
53 | typedef struct user_info_t { | ||
54 | u_int user_magic; | ||
55 | int event_head, event_tail; | ||
56 | event_t event[MAX_EVENTS]; | ||
57 | struct user_info_t *next; | ||
58 | struct pcmcia_socket *socket; | ||
59 | } user_info_t; | ||
60 | |||
61 | |||
62 | #ifdef DEBUG | ||
63 | extern int ds_pc_debug; | ||
64 | #define cs_socket_name(skt) ((skt)->dev.class_id) | ||
65 | |||
66 | #define ds_dbg(lvl, fmt, arg...) do { \ | ||
67 | if (ds_pc_debug >= lvl) \ | ||
68 | printk(KERN_DEBUG "ds: " fmt , ## arg); \ | ||
69 | } while (0) | ||
70 | #else | ||
71 | #define ds_dbg(lvl, fmt, arg...) do { } while (0) | ||
72 | #endif | ||
73 | |||
74 | static const char *release = "Linux Kernel Card Services"; | ||
75 | |||
76 | /** pcmcia_get_card_services_info | ||
77 | * | ||
78 | * Return information about this version of Card Services | ||
79 | */ | ||
80 | static int pcmcia_get_card_services_info(servinfo_t *info) | ||
81 | { | ||
82 | unsigned int socket_count = 0; | ||
83 | struct list_head *tmp; | ||
84 | info->Signature[0] = 'C'; | ||
85 | info->Signature[1] = 'S'; | ||
86 | down_read(&pcmcia_socket_list_rwsem); | ||
87 | list_for_each(tmp, &pcmcia_socket_list) | ||
88 | socket_count++; | ||
89 | up_read(&pcmcia_socket_list_rwsem); | ||
90 | info->Count = socket_count; | ||
91 | info->Revision = CS_RELEASE_CODE; | ||
92 | info->CSLevel = 0x0210; | ||
93 | info->VendorString = (char *)release; | ||
94 | return CS_SUCCESS; | ||
95 | } /* get_card_services_info */ | ||
96 | |||
97 | |||
98 | /* backwards-compatible accessing of driver --- by name! */ | ||
99 | |||
100 | static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) | ||
101 | { | ||
102 | struct device_driver *drv; | ||
103 | struct pcmcia_driver *p_drv; | ||
104 | |||
105 | drv = driver_find((char *) dev_info, &pcmcia_bus_type); | ||
106 | if (!drv) | ||
107 | return NULL; | ||
108 | |||
109 | p_drv = container_of(drv, struct pcmcia_driver, drv); | ||
110 | |||
111 | return (p_drv); | ||
112 | } | ||
113 | |||
114 | |||
115 | #ifdef CONFIG_PROC_FS | ||
116 | static struct proc_dir_entry *proc_pccard = NULL; | ||
117 | |||
118 | static int proc_read_drivers_callback(struct device_driver *driver, void *d) | ||
119 | { | ||
120 | char **p = d; | ||
121 | struct pcmcia_driver *p_drv = container_of(driver, | ||
122 | struct pcmcia_driver, drv); | ||
123 | |||
124 | *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name, | ||
125 | #ifdef CONFIG_MODULE_UNLOAD | ||
126 | (p_drv->owner) ? module_refcount(p_drv->owner) : 1 | ||
127 | #else | ||
128 | 1 | ||
129 | #endif | ||
130 | ); | ||
131 | d = (void *) p; | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int proc_read_drivers(char *buf, char **start, off_t pos, | ||
137 | int count, int *eof, void *data) | ||
138 | { | ||
139 | char *p = buf; | ||
140 | |||
141 | bus_for_each_drv(&pcmcia_bus_type, NULL, | ||
142 | (void *) &p, proc_read_drivers_callback); | ||
143 | |||
144 | return (p - buf); | ||
145 | } | ||
146 | #endif | ||
147 | |||
148 | /*====================================================================== | ||
149 | |||
150 | These manage a ring buffer of events pending for one user process | ||
151 | |||
152 | ======================================================================*/ | ||
153 | |||
154 | |||
155 | static int queue_empty(user_info_t *user) | ||
156 | { | ||
157 | return (user->event_head == user->event_tail); | ||
158 | } | ||
159 | |||
160 | static event_t get_queued_event(user_info_t *user) | ||
161 | { | ||
162 | user->event_tail = (user->event_tail+1) % MAX_EVENTS; | ||
163 | return user->event[user->event_tail]; | ||
164 | } | ||
165 | |||
166 | static void queue_event(user_info_t *user, event_t event) | ||
167 | { | ||
168 | user->event_head = (user->event_head+1) % MAX_EVENTS; | ||
169 | if (user->event_head == user->event_tail) | ||
170 | user->event_tail = (user->event_tail+1) % MAX_EVENTS; | ||
171 | user->event[user->event_head] = event; | ||
172 | } | ||
173 | |||
174 | void handle_event(struct pcmcia_socket *s, event_t event) | ||
175 | { | ||
176 | user_info_t *user; | ||
177 | for (user = s->user; user; user = user->next) | ||
178 | queue_event(user, event); | ||
179 | wake_up_interruptible(&s->queue); | ||
180 | } | ||
181 | |||
182 | |||
183 | /*====================================================================== | ||
184 | |||
185 | bind_request() and bind_device() are merged by now. Register_client() | ||
186 | is called right at the end of bind_request(), during the driver's | ||
187 | ->attach() call. Individual descriptions: | ||
188 | |||
189 | bind_request() connects a socket to a particular client driver. | ||
190 | It looks up the specified device ID in the list of registered | ||
191 | drivers, binds it to the socket, and tries to create an instance | ||
192 | of the device. unbind_request() deletes a driver instance. | ||
193 | |||
194 | Bind_device() associates a device driver with a particular socket. | ||
195 | It is normally called by Driver Services after it has identified | ||
196 | a newly inserted card. An instance of that driver will then be | ||
197 | eligible to register as a client of this socket. | ||
198 | |||
199 | Register_client() uses the dev_info_t handle to match the | ||
200 | caller with a socket. The driver must have already been bound | ||
201 | to a socket with bind_device() -- in fact, bind_device() | ||
202 | allocates the client structure that will be used. | ||
203 | |||
204 | ======================================================================*/ | ||
205 | |||
206 | static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info) | ||
207 | { | ||
208 | struct pcmcia_driver *p_drv; | ||
209 | struct pcmcia_device *p_dev; | ||
210 | int ret = 0; | ||
211 | unsigned long flags; | ||
212 | |||
213 | s = pcmcia_get_socket(s); | ||
214 | if (!s) | ||
215 | return -EINVAL; | ||
216 | |||
217 | ds_dbg(2, "bind_request(%d, '%s')\n", s->sock, | ||
218 | (char *)bind_info->dev_info); | ||
219 | |||
220 | p_drv = get_pcmcia_driver(&bind_info->dev_info); | ||
221 | if (!p_drv) { | ||
222 | ret = -EINVAL; | ||
223 | goto err_put; | ||
224 | } | ||
225 | |||
226 | if (!try_module_get(p_drv->owner)) { | ||
227 | ret = -EINVAL; | ||
228 | goto err_put_driver; | ||
229 | } | ||
230 | |||
231 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
232 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { | ||
233 | if (p_dev->func == bind_info->function) { | ||
234 | if ((p_dev->dev.driver == &p_drv->drv)) { | ||
235 | if (p_dev->cardmgr) { | ||
236 | /* if there's already a device | ||
237 | * registered, and it was registered | ||
238 | * by userspace before, we need to | ||
239 | * return the "instance". */ | ||
240 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
241 | bind_info->instance = p_dev->instance; | ||
242 | ret = -EBUSY; | ||
243 | goto err_put_module; | ||
244 | } else { | ||
245 | /* the correct driver managed to bind | ||
246 | * itself magically to the correct | ||
247 | * device. */ | ||
248 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
249 | p_dev->cardmgr = p_drv; | ||
250 | ret = 0; | ||
251 | goto err_put_module; | ||
252 | } | ||
253 | } else if (!p_dev->dev.driver) { | ||
254 | /* there's already a device available where | ||
255 | * no device has been bound to yet. So we don't | ||
256 | * need to register a device! */ | ||
257 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
258 | goto rescan; | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
263 | |||
264 | p_dev = pcmcia_device_add(s, bind_info->function); | ||
265 | if (!p_dev) { | ||
266 | ret = -EIO; | ||
267 | goto err_put_module; | ||
268 | } | ||
269 | |||
270 | rescan: | ||
271 | p_dev->cardmgr = p_drv; | ||
272 | |||
273 | /* if a driver is already running, we can abort */ | ||
274 | if (p_dev->dev.driver) | ||
275 | goto err_put_module; | ||
276 | |||
277 | /* | ||
278 | * Prevent this racing with a card insertion. | ||
279 | */ | ||
280 | down(&s->skt_sem); | ||
281 | bus_rescan_devices(&pcmcia_bus_type); | ||
282 | up(&s->skt_sem); | ||
283 | |||
284 | /* check whether the driver indeed matched. I don't care if this | ||
285 | * is racy or not, because it can only happen on cardmgr access | ||
286 | * paths... | ||
287 | */ | ||
288 | if (!(p_dev->dev.driver == &p_drv->drv)) | ||
289 | p_dev->cardmgr = NULL; | ||
290 | |||
291 | err_put_module: | ||
292 | module_put(p_drv->owner); | ||
293 | err_put_driver: | ||
294 | put_driver(&p_drv->drv); | ||
295 | err_put: | ||
296 | pcmcia_put_socket(s); | ||
297 | |||
298 | return (ret); | ||
299 | } /* bind_request */ | ||
300 | |||
301 | #ifdef CONFIG_CARDBUS | ||
302 | |||
303 | static struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s) | ||
304 | { | ||
305 | if (!s || !(s->state & SOCKET_CARDBUS)) | ||
306 | return NULL; | ||
307 | |||
308 | return s->cb_dev->subordinate; | ||
309 | } | ||
310 | #endif | ||
311 | |||
312 | static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first) | ||
313 | { | ||
314 | dev_node_t *node; | ||
315 | struct pcmcia_device *p_dev; | ||
316 | unsigned long flags; | ||
317 | int ret = 0; | ||
318 | |||
319 | #ifdef CONFIG_CARDBUS | ||
320 | /* | ||
321 | * Some unbelievably ugly code to associate the PCI cardbus | ||
322 | * device and its driver with the PCMCIA "bind" information. | ||
323 | */ | ||
324 | { | ||
325 | struct pci_bus *bus; | ||
326 | |||
327 | bus = pcmcia_lookup_bus(s); | ||
328 | if (bus) { | ||
329 | struct list_head *list; | ||
330 | struct pci_dev *dev = NULL; | ||
331 | |||
332 | list = bus->devices.next; | ||
333 | while (list != &bus->devices) { | ||
334 | struct pci_dev *pdev = pci_dev_b(list); | ||
335 | list = list->next; | ||
336 | |||
337 | if (first) { | ||
338 | dev = pdev; | ||
339 | break; | ||
340 | } | ||
341 | |||
342 | /* Try to handle "next" here some way? */ | ||
343 | } | ||
344 | if (dev && dev->driver) { | ||
345 | strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN); | ||
346 | bind_info->major = 0; | ||
347 | bind_info->minor = 0; | ||
348 | bind_info->next = NULL; | ||
349 | return 0; | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | #endif | ||
354 | |||
355 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
356 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { | ||
357 | if (p_dev->func == bind_info->function) { | ||
358 | p_dev = pcmcia_get_dev(p_dev); | ||
359 | if (!p_dev) | ||
360 | continue; | ||
361 | goto found; | ||
362 | } | ||
363 | } | ||
364 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
365 | return -ENODEV; | ||
366 | |||
367 | found: | ||
368 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
369 | |||
370 | if ((!p_dev->instance) || | ||
371 | (p_dev->instance->state & DEV_CONFIG_PENDING)) { | ||
372 | ret = -EAGAIN; | ||
373 | goto err_put; | ||
374 | } | ||
375 | |||
376 | if (first) | ||
377 | node = p_dev->instance->dev; | ||
378 | else | ||
379 | for (node = p_dev->instance->dev; node; node = node->next) | ||
380 | if (node == bind_info->next) | ||
381 | break; | ||
382 | if (!node) { | ||
383 | ret = -ENODEV; | ||
384 | goto err_put; | ||
385 | } | ||
386 | |||
387 | strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); | ||
388 | bind_info->major = node->major; | ||
389 | bind_info->minor = node->minor; | ||
390 | bind_info->next = node->next; | ||
391 | |||
392 | err_put: | ||
393 | pcmcia_put_dev(p_dev); | ||
394 | return (ret); | ||
395 | } /* get_device_info */ | ||
396 | |||
397 | |||
398 | static int ds_open(struct inode *inode, struct file *file) | ||
399 | { | ||
400 | socket_t i = iminor(inode); | ||
401 | struct pcmcia_socket *s; | ||
402 | user_info_t *user; | ||
403 | |||
404 | ds_dbg(0, "ds_open(socket %d)\n", i); | ||
405 | |||
406 | s = pcmcia_get_socket_by_nr(i); | ||
407 | if (!s) | ||
408 | return -ENODEV; | ||
409 | s = pcmcia_get_socket(s); | ||
410 | if (!s) | ||
411 | return -ENODEV; | ||
412 | |||
413 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
414 | if (s->pcmcia_state.busy) { | ||
415 | pcmcia_put_socket(s); | ||
416 | return -EBUSY; | ||
417 | } | ||
418 | else | ||
419 | s->pcmcia_state.busy = 1; | ||
420 | } | ||
421 | |||
422 | user = kmalloc(sizeof(user_info_t), GFP_KERNEL); | ||
423 | if (!user) { | ||
424 | pcmcia_put_socket(s); | ||
425 | return -ENOMEM; | ||
426 | } | ||
427 | user->event_tail = user->event_head = 0; | ||
428 | user->next = s->user; | ||
429 | user->user_magic = USER_MAGIC; | ||
430 | user->socket = s; | ||
431 | s->user = user; | ||
432 | file->private_data = user; | ||
433 | |||
434 | if (s->pcmcia_state.present) | ||
435 | queue_event(user, CS_EVENT_CARD_INSERTION); | ||
436 | return 0; | ||
437 | } /* ds_open */ | ||
438 | |||
439 | /*====================================================================*/ | ||
440 | |||
441 | static int ds_release(struct inode *inode, struct file *file) | ||
442 | { | ||
443 | struct pcmcia_socket *s; | ||
444 | user_info_t *user, **link; | ||
445 | |||
446 | ds_dbg(0, "ds_release(socket %d)\n", iminor(inode)); | ||
447 | |||
448 | user = file->private_data; | ||
449 | if (CHECK_USER(user)) | ||
450 | goto out; | ||
451 | |||
452 | s = user->socket; | ||
453 | |||
454 | /* Unlink user data structure */ | ||
455 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
456 | s->pcmcia_state.busy = 0; | ||
457 | } | ||
458 | file->private_data = NULL; | ||
459 | for (link = &s->user; *link; link = &(*link)->next) | ||
460 | if (*link == user) break; | ||
461 | if (link == NULL) | ||
462 | goto out; | ||
463 | *link = user->next; | ||
464 | user->user_magic = 0; | ||
465 | kfree(user); | ||
466 | pcmcia_put_socket(s); | ||
467 | out: | ||
468 | return 0; | ||
469 | } /* ds_release */ | ||
470 | |||
471 | /*====================================================================*/ | ||
472 | |||
473 | static ssize_t ds_read(struct file *file, char __user *buf, | ||
474 | size_t count, loff_t *ppos) | ||
475 | { | ||
476 | struct pcmcia_socket *s; | ||
477 | user_info_t *user; | ||
478 | int ret; | ||
479 | |||
480 | ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode)); | ||
481 | |||
482 | if (count < 4) | ||
483 | return -EINVAL; | ||
484 | |||
485 | user = file->private_data; | ||
486 | if (CHECK_USER(user)) | ||
487 | return -EIO; | ||
488 | |||
489 | s = user->socket; | ||
490 | if (s->pcmcia_state.dead) | ||
491 | return -EIO; | ||
492 | |||
493 | ret = wait_event_interruptible(s->queue, !queue_empty(user)); | ||
494 | if (ret == 0) | ||
495 | ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; | ||
496 | |||
497 | return ret; | ||
498 | } /* ds_read */ | ||
499 | |||
500 | /*====================================================================*/ | ||
501 | |||
502 | static ssize_t ds_write(struct file *file, const char __user *buf, | ||
503 | size_t count, loff_t *ppos) | ||
504 | { | ||
505 | ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode)); | ||
506 | |||
507 | if (count != 4) | ||
508 | return -EINVAL; | ||
509 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | ||
510 | return -EBADF; | ||
511 | |||
512 | return -EIO; | ||
513 | } /* ds_write */ | ||
514 | |||
515 | /*====================================================================*/ | ||
516 | |||
517 | /* No kernel lock - fine */ | ||
518 | static u_int ds_poll(struct file *file, poll_table *wait) | ||
519 | { | ||
520 | struct pcmcia_socket *s; | ||
521 | user_info_t *user; | ||
522 | |||
523 | ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode)); | ||
524 | |||
525 | user = file->private_data; | ||
526 | if (CHECK_USER(user)) | ||
527 | return POLLERR; | ||
528 | s = user->socket; | ||
529 | /* | ||
530 | * We don't check for a dead socket here since that | ||
531 | * will send cardmgr into an endless spin. | ||
532 | */ | ||
533 | poll_wait(file, &s->queue, wait); | ||
534 | if (!queue_empty(user)) | ||
535 | return POLLIN | POLLRDNORM; | ||
536 | return 0; | ||
537 | } /* ds_poll */ | ||
538 | |||
539 | /*====================================================================*/ | ||
540 | |||
541 | extern int pcmcia_adjust_resource_info(adjust_t *adj); | ||
542 | |||
543 | static int ds_ioctl(struct inode * inode, struct file * file, | ||
544 | u_int cmd, u_long arg) | ||
545 | { | ||
546 | struct pcmcia_socket *s; | ||
547 | void __user *uarg = (char __user *)arg; | ||
548 | u_int size; | ||
549 | int ret, err; | ||
550 | ds_ioctl_arg_t *buf; | ||
551 | user_info_t *user; | ||
552 | |||
553 | ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg); | ||
554 | |||
555 | user = file->private_data; | ||
556 | if (CHECK_USER(user)) | ||
557 | return -EIO; | ||
558 | |||
559 | s = user->socket; | ||
560 | if (s->pcmcia_state.dead) | ||
561 | return -EIO; | ||
562 | |||
563 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; | ||
564 | if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; | ||
565 | |||
566 | /* Permission check */ | ||
567 | if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN)) | ||
568 | return -EPERM; | ||
569 | |||
570 | if (cmd & IOC_IN) { | ||
571 | if (!access_ok(VERIFY_READ, uarg, size)) { | ||
572 | ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT); | ||
573 | return -EFAULT; | ||
574 | } | ||
575 | } | ||
576 | if (cmd & IOC_OUT) { | ||
577 | if (!access_ok(VERIFY_WRITE, uarg, size)) { | ||
578 | ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT); | ||
579 | return -EFAULT; | ||
580 | } | ||
581 | } | ||
582 | buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL); | ||
583 | if (!buf) | ||
584 | return -ENOMEM; | ||
585 | |||
586 | err = ret = 0; | ||
587 | |||
588 | if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size); | ||
589 | |||
590 | switch (cmd) { | ||
591 | case DS_ADJUST_RESOURCE_INFO: | ||
592 | ret = pcmcia_adjust_resource_info(&buf->adjust); | ||
593 | break; | ||
594 | case DS_GET_CARD_SERVICES_INFO: | ||
595 | ret = pcmcia_get_card_services_info(&buf->servinfo); | ||
596 | break; | ||
597 | case DS_GET_CONFIGURATION_INFO: | ||
598 | if (buf->config.Function && | ||
599 | (buf->config.Function >= s->functions)) | ||
600 | ret = CS_BAD_ARGS; | ||
601 | else | ||
602 | ret = pccard_get_configuration_info(s, | ||
603 | buf->config.Function, &buf->config); | ||
604 | break; | ||
605 | case DS_GET_FIRST_TUPLE: | ||
606 | down(&s->skt_sem); | ||
607 | pcmcia_validate_mem(s); | ||
608 | up(&s->skt_sem); | ||
609 | ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple); | ||
610 | break; | ||
611 | case DS_GET_NEXT_TUPLE: | ||
612 | ret = pccard_get_next_tuple(s, BIND_FN_ALL, &buf->tuple); | ||
613 | break; | ||
614 | case DS_GET_TUPLE_DATA: | ||
615 | buf->tuple.TupleData = buf->tuple_parse.data; | ||
616 | buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data); | ||
617 | ret = pccard_get_tuple_data(s, &buf->tuple); | ||
618 | break; | ||
619 | case DS_PARSE_TUPLE: | ||
620 | buf->tuple.TupleData = buf->tuple_parse.data; | ||
621 | ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse); | ||
622 | break; | ||
623 | case DS_RESET_CARD: | ||
624 | ret = pccard_reset_card(s); | ||
625 | break; | ||
626 | case DS_GET_STATUS: | ||
627 | if (buf->status.Function && | ||
628 | (buf->status.Function >= s->functions)) | ||
629 | ret = CS_BAD_ARGS; | ||
630 | else | ||
631 | ret = pccard_get_status(s, buf->status.Function, &buf->status); | ||
632 | break; | ||
633 | case DS_VALIDATE_CIS: | ||
634 | down(&s->skt_sem); | ||
635 | pcmcia_validate_mem(s); | ||
636 | up(&s->skt_sem); | ||
637 | ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo); | ||
638 | break; | ||
639 | case DS_SUSPEND_CARD: | ||
640 | ret = pcmcia_suspend_card(s); | ||
641 | break; | ||
642 | case DS_RESUME_CARD: | ||
643 | ret = pcmcia_resume_card(s); | ||
644 | break; | ||
645 | case DS_EJECT_CARD: | ||
646 | err = pcmcia_eject_card(s); | ||
647 | break; | ||
648 | case DS_INSERT_CARD: | ||
649 | err = pcmcia_insert_card(s); | ||
650 | break; | ||
651 | case DS_ACCESS_CONFIGURATION_REGISTER: | ||
652 | if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) { | ||
653 | err = -EPERM; | ||
654 | goto free_out; | ||
655 | } | ||
656 | if (buf->conf_reg.Function && | ||
657 | (buf->conf_reg.Function >= s->functions)) | ||
658 | ret = CS_BAD_ARGS; | ||
659 | else | ||
660 | ret = pccard_access_configuration_register(s, | ||
661 | buf->conf_reg.Function, &buf->conf_reg); | ||
662 | break; | ||
663 | case DS_GET_FIRST_REGION: | ||
664 | case DS_GET_NEXT_REGION: | ||
665 | case DS_BIND_MTD: | ||
666 | if (!capable(CAP_SYS_ADMIN)) { | ||
667 | err = -EPERM; | ||
668 | goto free_out; | ||
669 | } else { | ||
670 | static int printed = 0; | ||
671 | if (!printed) { | ||
672 | printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n"); | ||
673 | printk(KERN_WARNING "MTD handling any more.\n"); | ||
674 | printed++; | ||
675 | } | ||
676 | } | ||
677 | err = -EINVAL; | ||
678 | goto free_out; | ||
679 | break; | ||
680 | case DS_GET_FIRST_WINDOW: | ||
681 | ret = pcmcia_get_window(s, &buf->win_info.handle, 0, | ||
682 | &buf->win_info.window); | ||
683 | break; | ||
684 | case DS_GET_NEXT_WINDOW: | ||
685 | ret = pcmcia_get_window(s, &buf->win_info.handle, | ||
686 | buf->win_info.handle->index + 1, &buf->win_info.window); | ||
687 | break; | ||
688 | case DS_GET_MEM_PAGE: | ||
689 | ret = pcmcia_get_mem_page(buf->win_info.handle, | ||
690 | &buf->win_info.map); | ||
691 | break; | ||
692 | case DS_REPLACE_CIS: | ||
693 | ret = pcmcia_replace_cis(s, &buf->cisdump); | ||
694 | break; | ||
695 | case DS_BIND_REQUEST: | ||
696 | if (!capable(CAP_SYS_ADMIN)) { | ||
697 | err = -EPERM; | ||
698 | goto free_out; | ||
699 | } | ||
700 | err = bind_request(s, &buf->bind_info); | ||
701 | break; | ||
702 | case DS_GET_DEVICE_INFO: | ||
703 | err = get_device_info(s, &buf->bind_info, 1); | ||
704 | break; | ||
705 | case DS_GET_NEXT_DEVICE: | ||
706 | err = get_device_info(s, &buf->bind_info, 0); | ||
707 | break; | ||
708 | case DS_UNBIND_REQUEST: | ||
709 | err = 0; | ||
710 | break; | ||
711 | default: | ||
712 | err = -EINVAL; | ||
713 | } | ||
714 | |||
715 | if ((err == 0) && (ret != CS_SUCCESS)) { | ||
716 | ds_dbg(2, "ds_ioctl: ret = %d\n", ret); | ||
717 | switch (ret) { | ||
718 | case CS_BAD_SOCKET: case CS_NO_CARD: | ||
719 | err = -ENODEV; break; | ||
720 | case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ: | ||
721 | case CS_BAD_TUPLE: | ||
722 | err = -EINVAL; break; | ||
723 | case CS_IN_USE: | ||
724 | err = -EBUSY; break; | ||
725 | case CS_OUT_OF_RESOURCE: | ||
726 | err = -ENOSPC; break; | ||
727 | case CS_NO_MORE_ITEMS: | ||
728 | err = -ENODATA; break; | ||
729 | case CS_UNSUPPORTED_FUNCTION: | ||
730 | err = -ENOSYS; break; | ||
731 | default: | ||
732 | err = -EIO; break; | ||
733 | } | ||
734 | } | ||
735 | |||
736 | if (cmd & IOC_OUT) { | ||
737 | if (__copy_to_user(uarg, (char *)buf, size)) | ||
738 | err = -EFAULT; | ||
739 | } | ||
740 | |||
741 | free_out: | ||
742 | kfree(buf); | ||
743 | return err; | ||
744 | } /* ds_ioctl */ | ||
745 | |||
746 | /*====================================================================*/ | ||
747 | |||
748 | static struct file_operations ds_fops = { | ||
749 | .owner = THIS_MODULE, | ||
750 | .open = ds_open, | ||
751 | .release = ds_release, | ||
752 | .ioctl = ds_ioctl, | ||
753 | .read = ds_read, | ||
754 | .write = ds_write, | ||
755 | .poll = ds_poll, | ||
756 | }; | ||
757 | |||
758 | void __init pcmcia_setup_ioctl(void) { | ||
759 | int i; | ||
760 | |||
761 | /* Set up character device for user mode clients */ | ||
762 | i = register_chrdev(0, "pcmcia", &ds_fops); | ||
763 | if (i < 0) | ||
764 | printk(KERN_NOTICE "unable to find a free device # for " | ||
765 | "Driver Services (error=%d)\n", i); | ||
766 | else | ||
767 | major_dev = i; | ||
768 | |||
769 | #ifdef CONFIG_PROC_FS | ||
770 | proc_pccard = proc_mkdir("pccard", proc_bus); | ||
771 | if (proc_pccard) | ||
772 | create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL); | ||
773 | #endif | ||
774 | } | ||
775 | |||
776 | |||
777 | void __exit pcmcia_cleanup_ioctl(void) { | ||
778 | #ifdef CONFIG_PROC_FS | ||
779 | if (proc_pccard) { | ||
780 | remove_proc_entry("drivers", proc_pccard); | ||
781 | remove_proc_entry("pccard", proc_bus); | ||
782 | } | ||
783 | #endif | ||
784 | if (major_dev != -1) | ||
785 | unregister_chrdev(major_dev, "pcmcia"); | ||
786 | } | ||
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c new file mode 100644 index 000000000000..c01dc6bf1526 --- /dev/null +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -0,0 +1,998 @@ | |||
1 | /* | ||
2 | * PCMCIA 16-bit resource management functions | ||
3 | * | ||
4 | * The initial developer of the original code is David A. Hinds | ||
5 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
7 | * | ||
8 | * Copyright (C) 1999 David A. Hinds | ||
9 | * Copyright (C) 2004-2005 Dominik Brodowski | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/config.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/device.h> | ||
24 | |||
25 | #define IN_CARD_SERVICES | ||
26 | #include <pcmcia/version.h> | ||
27 | #include <pcmcia/cs_types.h> | ||
28 | #include <pcmcia/ss.h> | ||
29 | #include <pcmcia/cs.h> | ||
30 | #include <pcmcia/bulkmem.h> | ||
31 | #include <pcmcia/cistpl.h> | ||
32 | #include <pcmcia/cisreg.h> | ||
33 | #include <pcmcia/ds.h> | ||
34 | |||
35 | #include "cs_internal.h" | ||
36 | #include "ds_internal.h" | ||
37 | |||
38 | |||
39 | /* Access speed for IO windows */ | ||
40 | static int io_speed = 0; | ||
41 | module_param(io_speed, int, 0444); | ||
42 | |||
43 | |||
44 | #ifdef CONFIG_PCMCIA_PROBE | ||
45 | /* mask of IRQs already reserved by other cards, we should avoid using them */ | ||
46 | static u8 pcmcia_used_irq[NR_IRQS]; | ||
47 | #endif | ||
48 | |||
49 | |||
50 | #ifdef DEBUG | ||
51 | extern int ds_pc_debug; | ||
52 | #define cs_socket_name(skt) ((skt)->dev.class_id) | ||
53 | |||
54 | #define ds_dbg(skt, lvl, fmt, arg...) do { \ | ||
55 | if (ds_pc_debug >= lvl) \ | ||
56 | printk(KERN_DEBUG "pcmcia_resource: %s: " fmt, \ | ||
57 | cs_socket_name(skt) , ## arg); \ | ||
58 | } while (0) | ||
59 | #else | ||
60 | #define ds_dbg(lvl, fmt, arg...) do { } while (0) | ||
61 | #endif | ||
62 | |||
63 | |||
64 | |||
65 | /** alloc_io_space | ||
66 | * | ||
67 | * Special stuff for managing IO windows, because they are scarce | ||
68 | */ | ||
69 | |||
70 | static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, | ||
71 | ioaddr_t num, u_int lines) | ||
72 | { | ||
73 | int i; | ||
74 | kio_addr_t try, align; | ||
75 | |||
76 | align = (*base) ? (lines ? 1<<lines : 0) : 1; | ||
77 | if (align && (align < num)) { | ||
78 | if (*base) { | ||
79 | ds_dbg(s, 0, "odd IO request: num %#x align %#lx\n", | ||
80 | num, align); | ||
81 | align = 0; | ||
82 | } else | ||
83 | while (align && (align < num)) align <<= 1; | ||
84 | } | ||
85 | if (*base & ~(align-1)) { | ||
86 | ds_dbg(s, 0, "odd IO request: base %#x align %#lx\n", | ||
87 | *base, align); | ||
88 | align = 0; | ||
89 | } | ||
90 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { | ||
91 | *base = s->io_offset | (*base & 0x0fff); | ||
92 | s->io[0].Attributes = attr; | ||
93 | return 0; | ||
94 | } | ||
95 | /* Check for an already-allocated window that must conflict with | ||
96 | * what was asked for. It is a hack because it does not catch all | ||
97 | * potential conflicts, just the most obvious ones. | ||
98 | */ | ||
99 | for (i = 0; i < MAX_IO_WIN; i++) | ||
100 | if ((s->io[i].NumPorts != 0) && | ||
101 | ((s->io[i].BasePort & (align-1)) == *base)) | ||
102 | return 1; | ||
103 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
104 | if (s->io[i].NumPorts == 0) { | ||
105 | s->io[i].res = pcmcia_find_io_region(*base, num, align, s); | ||
106 | if (s->io[i].res) { | ||
107 | s->io[i].Attributes = attr; | ||
108 | s->io[i].BasePort = *base = s->io[i].res->start; | ||
109 | s->io[i].NumPorts = s->io[i].InUse = num; | ||
110 | break; | ||
111 | } else | ||
112 | return 1; | ||
113 | } else if (s->io[i].Attributes != attr) | ||
114 | continue; | ||
115 | /* Try to extend top of window */ | ||
116 | try = s->io[i].BasePort + s->io[i].NumPorts; | ||
117 | if ((*base == 0) || (*base == try)) | ||
118 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, | ||
119 | s->io[i].res->end + num, s) == 0) { | ||
120 | *base = try; | ||
121 | s->io[i].NumPorts += num; | ||
122 | s->io[i].InUse += num; | ||
123 | break; | ||
124 | } | ||
125 | /* Try to extend bottom of window */ | ||
126 | try = s->io[i].BasePort - num; | ||
127 | if ((*base == 0) || (*base == try)) | ||
128 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, | ||
129 | s->io[i].res->end, s) == 0) { | ||
130 | s->io[i].BasePort = *base = try; | ||
131 | s->io[i].NumPorts += num; | ||
132 | s->io[i].InUse += num; | ||
133 | break; | ||
134 | } | ||
135 | } | ||
136 | return (i == MAX_IO_WIN); | ||
137 | } /* alloc_io_space */ | ||
138 | |||
139 | |||
140 | static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, | ||
141 | ioaddr_t num) | ||
142 | { | ||
143 | int i; | ||
144 | |||
145 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
146 | if ((s->io[i].BasePort <= base) && | ||
147 | (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) { | ||
148 | s->io[i].InUse -= num; | ||
149 | /* Free the window if no one else is using it */ | ||
150 | if (s->io[i].InUse == 0) { | ||
151 | s->io[i].NumPorts = 0; | ||
152 | release_resource(s->io[i].res); | ||
153 | kfree(s->io[i].res); | ||
154 | s->io[i].res = NULL; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | } /* release_io_space */ | ||
159 | |||
160 | |||
161 | /** pccard_access_configuration_register | ||
162 | * | ||
163 | * Access_configuration_register() reads and writes configuration | ||
164 | * registers in attribute memory. Memory window 0 is reserved for | ||
165 | * this and the tuple reading services. | ||
166 | */ | ||
167 | |||
168 | int pccard_access_configuration_register(struct pcmcia_socket *s, | ||
169 | unsigned int function, | ||
170 | conf_reg_t *reg) | ||
171 | { | ||
172 | config_t *c; | ||
173 | int addr; | ||
174 | u_char val; | ||
175 | |||
176 | if (!s || !s->config) | ||
177 | return CS_NO_CARD; | ||
178 | |||
179 | c = &s->config[function]; | ||
180 | |||
181 | if (c == NULL) | ||
182 | return CS_NO_CARD; | ||
183 | |||
184 | if (!(c->state & CONFIG_LOCKED)) | ||
185 | return CS_CONFIGURATION_LOCKED; | ||
186 | |||
187 | addr = (c->ConfigBase + reg->Offset) >> 1; | ||
188 | |||
189 | switch (reg->Action) { | ||
190 | case CS_READ: | ||
191 | pcmcia_read_cis_mem(s, 1, addr, 1, &val); | ||
192 | reg->Value = val; | ||
193 | break; | ||
194 | case CS_WRITE: | ||
195 | val = reg->Value; | ||
196 | pcmcia_write_cis_mem(s, 1, addr, 1, &val); | ||
197 | break; | ||
198 | default: | ||
199 | return CS_BAD_ARGS; | ||
200 | break; | ||
201 | } | ||
202 | return CS_SUCCESS; | ||
203 | } /* pccard_access_configuration_register */ | ||
204 | |||
205 | int pcmcia_access_configuration_register(client_handle_t handle, | ||
206 | conf_reg_t *reg) | ||
207 | { | ||
208 | struct pcmcia_socket *s; | ||
209 | if (CHECK_HANDLE(handle)) | ||
210 | return CS_BAD_HANDLE; | ||
211 | s = SOCKET(handle); | ||
212 | return pccard_access_configuration_register(s, handle->Function, reg); | ||
213 | } | ||
214 | EXPORT_SYMBOL(pcmcia_access_configuration_register); | ||
215 | |||
216 | |||
217 | |||
218 | int pccard_get_configuration_info(struct pcmcia_socket *s, | ||
219 | unsigned int function, | ||
220 | config_info_t *config) | ||
221 | { | ||
222 | config_t *c; | ||
223 | |||
224 | if (!(s->state & SOCKET_PRESENT)) | ||
225 | return CS_NO_CARD; | ||
226 | |||
227 | config->Function = function; | ||
228 | |||
229 | #ifdef CONFIG_CARDBUS | ||
230 | if (s->state & SOCKET_CARDBUS) { | ||
231 | memset(config, 0, sizeof(config_info_t)); | ||
232 | config->Vcc = s->socket.Vcc; | ||
233 | config->Vpp1 = config->Vpp2 = s->socket.Vpp; | ||
234 | config->Option = s->cb_dev->subordinate->number; | ||
235 | if (s->state & SOCKET_CARDBUS_CONFIG) { | ||
236 | config->Attributes = CONF_VALID_CLIENT; | ||
237 | config->IntType = INT_CARDBUS; | ||
238 | config->AssignedIRQ = s->irq.AssignedIRQ; | ||
239 | if (config->AssignedIRQ) | ||
240 | config->Attributes |= CONF_ENABLE_IRQ; | ||
241 | config->BasePort1 = s->io[0].BasePort; | ||
242 | config->NumPorts1 = s->io[0].NumPorts; | ||
243 | } | ||
244 | return CS_SUCCESS; | ||
245 | } | ||
246 | #endif | ||
247 | |||
248 | c = (s->config != NULL) ? &s->config[function] : NULL; | ||
249 | |||
250 | if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { | ||
251 | config->Attributes = 0; | ||
252 | config->Vcc = s->socket.Vcc; | ||
253 | config->Vpp1 = config->Vpp2 = s->socket.Vpp; | ||
254 | return CS_SUCCESS; | ||
255 | } | ||
256 | |||
257 | /* !!! This is a hack !!! */ | ||
258 | memcpy(&config->Attributes, &c->Attributes, sizeof(config_t)); | ||
259 | config->Attributes |= CONF_VALID_CLIENT; | ||
260 | config->CardValues = c->CardValues; | ||
261 | config->IRQAttributes = c->irq.Attributes; | ||
262 | config->AssignedIRQ = s->irq.AssignedIRQ; | ||
263 | config->BasePort1 = c->io.BasePort1; | ||
264 | config->NumPorts1 = c->io.NumPorts1; | ||
265 | config->Attributes1 = c->io.Attributes1; | ||
266 | config->BasePort2 = c->io.BasePort2; | ||
267 | config->NumPorts2 = c->io.NumPorts2; | ||
268 | config->Attributes2 = c->io.Attributes2; | ||
269 | config->IOAddrLines = c->io.IOAddrLines; | ||
270 | |||
271 | return CS_SUCCESS; | ||
272 | } /* pccard_get_configuration_info */ | ||
273 | |||
274 | int pcmcia_get_configuration_info(client_handle_t handle, | ||
275 | config_info_t *config) | ||
276 | { | ||
277 | struct pcmcia_socket *s; | ||
278 | |||
279 | if ((CHECK_HANDLE(handle)) || !config) | ||
280 | return CS_BAD_HANDLE; | ||
281 | s = SOCKET(handle); | ||
282 | if (!s) | ||
283 | return CS_BAD_HANDLE; | ||
284 | return pccard_get_configuration_info(s, handle->Function, config); | ||
285 | } | ||
286 | EXPORT_SYMBOL(pcmcia_get_configuration_info); | ||
287 | |||
288 | |||
289 | /** pcmcia_get_window | ||
290 | */ | ||
291 | int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, | ||
292 | int idx, win_req_t *req) | ||
293 | { | ||
294 | window_t *win; | ||
295 | int w; | ||
296 | |||
297 | if (!s || !(s->state & SOCKET_PRESENT)) | ||
298 | return CS_NO_CARD; | ||
299 | for (w = idx; w < MAX_WIN; w++) | ||
300 | if (s->state & SOCKET_WIN_REQ(w)) | ||
301 | break; | ||
302 | if (w == MAX_WIN) | ||
303 | return CS_NO_MORE_ITEMS; | ||
304 | win = &s->win[w]; | ||
305 | req->Base = win->ctl.res->start; | ||
306 | req->Size = win->ctl.res->end - win->ctl.res->start + 1; | ||
307 | req->AccessSpeed = win->ctl.speed; | ||
308 | req->Attributes = 0; | ||
309 | if (win->ctl.flags & MAP_ATTRIB) | ||
310 | req->Attributes |= WIN_MEMORY_TYPE_AM; | ||
311 | if (win->ctl.flags & MAP_ACTIVE) | ||
312 | req->Attributes |= WIN_ENABLE; | ||
313 | if (win->ctl.flags & MAP_16BIT) | ||
314 | req->Attributes |= WIN_DATA_WIDTH_16; | ||
315 | if (win->ctl.flags & MAP_USE_WAIT) | ||
316 | req->Attributes |= WIN_USE_WAIT; | ||
317 | *handle = win; | ||
318 | return CS_SUCCESS; | ||
319 | } /* pcmcia_get_window */ | ||
320 | EXPORT_SYMBOL(pcmcia_get_window); | ||
321 | |||
322 | |||
323 | /** pccard_get_status | ||
324 | * | ||
325 | * Get the current socket state bits. We don't support the latched | ||
326 | * SocketState yet: I haven't seen any point for it. | ||
327 | */ | ||
328 | |||
329 | int pccard_get_status(struct pcmcia_socket *s, unsigned int function, | ||
330 | cs_status_t *status) | ||
331 | { | ||
332 | config_t *c; | ||
333 | int val; | ||
334 | |||
335 | s->ops->get_status(s, &val); | ||
336 | status->CardState = status->SocketState = 0; | ||
337 | status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; | ||
338 | status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; | ||
339 | status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0; | ||
340 | status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0; | ||
341 | if (s->state & SOCKET_SUSPEND) | ||
342 | status->CardState |= CS_EVENT_PM_SUSPEND; | ||
343 | if (!(s->state & SOCKET_PRESENT)) | ||
344 | return CS_NO_CARD; | ||
345 | |||
346 | c = (s->config != NULL) ? &s->config[function] : NULL; | ||
347 | if ((c != NULL) && (c->state & CONFIG_LOCKED) && | ||
348 | (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { | ||
349 | u_char reg; | ||
350 | if (c->Present & PRESENT_PIN_REPLACE) { | ||
351 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); | ||
352 | status->CardState |= | ||
353 | (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; | ||
354 | status->CardState |= | ||
355 | (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0; | ||
356 | status->CardState |= | ||
357 | (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0; | ||
358 | status->CardState |= | ||
359 | (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0; | ||
360 | } else { | ||
361 | /* No PRR? Then assume we're always ready */ | ||
362 | status->CardState |= CS_EVENT_READY_CHANGE; | ||
363 | } | ||
364 | if (c->Present & PRESENT_EXT_STATUS) { | ||
365 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); | ||
366 | status->CardState |= | ||
367 | (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; | ||
368 | } | ||
369 | return CS_SUCCESS; | ||
370 | } | ||
371 | status->CardState |= | ||
372 | (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0; | ||
373 | status->CardState |= | ||
374 | (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0; | ||
375 | status->CardState |= | ||
376 | (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0; | ||
377 | status->CardState |= | ||
378 | (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; | ||
379 | return CS_SUCCESS; | ||
380 | } /* pccard_get_status */ | ||
381 | |||
382 | int pcmcia_get_status(client_handle_t handle, cs_status_t *status) | ||
383 | { | ||
384 | struct pcmcia_socket *s; | ||
385 | if (CHECK_HANDLE(handle)) | ||
386 | return CS_BAD_HANDLE; | ||
387 | s = SOCKET(handle); | ||
388 | return pccard_get_status(s, handle->Function, status); | ||
389 | } | ||
390 | EXPORT_SYMBOL(pcmcia_get_status); | ||
391 | |||
392 | |||
393 | |||
394 | /** pcmcia_get_mem_page | ||
395 | * | ||
396 | * Change the card address of an already open memory window. | ||
397 | */ | ||
398 | int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) | ||
399 | { | ||
400 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | ||
401 | return CS_BAD_HANDLE; | ||
402 | req->Page = 0; | ||
403 | req->CardOffset = win->ctl.card_start; | ||
404 | return CS_SUCCESS; | ||
405 | } /* pcmcia_get_mem_page */ | ||
406 | EXPORT_SYMBOL(pcmcia_get_mem_page); | ||
407 | |||
408 | |||
409 | int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) | ||
410 | { | ||
411 | struct pcmcia_socket *s; | ||
412 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | ||
413 | return CS_BAD_HANDLE; | ||
414 | if (req->Page != 0) | ||
415 | return CS_BAD_PAGE; | ||
416 | s = win->sock; | ||
417 | win->ctl.card_start = req->CardOffset; | ||
418 | if (s->ops->set_mem_map(s, &win->ctl) != 0) | ||
419 | return CS_BAD_OFFSET; | ||
420 | return CS_SUCCESS; | ||
421 | } /* pcmcia_map_mem_page */ | ||
422 | EXPORT_SYMBOL(pcmcia_map_mem_page); | ||
423 | |||
424 | |||
425 | /** pcmcia_modify_configuration | ||
426 | * | ||
427 | * Modify a locked socket configuration | ||
428 | */ | ||
429 | int pcmcia_modify_configuration(client_handle_t handle, | ||
430 | modconf_t *mod) | ||
431 | { | ||
432 | struct pcmcia_socket *s; | ||
433 | config_t *c; | ||
434 | |||
435 | if (CHECK_HANDLE(handle)) | ||
436 | return CS_BAD_HANDLE; | ||
437 | s = SOCKET(handle); | ||
438 | c = CONFIG(handle); | ||
439 | if (!(s->state & SOCKET_PRESENT)) | ||
440 | return CS_NO_CARD; | ||
441 | if (!(c->state & CONFIG_LOCKED)) | ||
442 | return CS_CONFIGURATION_LOCKED; | ||
443 | |||
444 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { | ||
445 | if (mod->Attributes & CONF_ENABLE_IRQ) { | ||
446 | c->Attributes |= CONF_ENABLE_IRQ; | ||
447 | s->socket.io_irq = s->irq.AssignedIRQ; | ||
448 | } else { | ||
449 | c->Attributes &= ~CONF_ENABLE_IRQ; | ||
450 | s->socket.io_irq = 0; | ||
451 | } | ||
452 | s->ops->set_socket(s, &s->socket); | ||
453 | } | ||
454 | |||
455 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) | ||
456 | return CS_BAD_VCC; | ||
457 | |||
458 | /* We only allow changing Vpp1 and Vpp2 to the same value */ | ||
459 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | ||
460 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | ||
461 | if (mod->Vpp1 != mod->Vpp2) | ||
462 | return CS_BAD_VPP; | ||
463 | c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1; | ||
464 | if (s->ops->set_socket(s, &s->socket)) | ||
465 | return CS_BAD_VPP; | ||
466 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | ||
467 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) | ||
468 | return CS_BAD_VPP; | ||
469 | |||
470 | return CS_SUCCESS; | ||
471 | } /* modify_configuration */ | ||
472 | EXPORT_SYMBOL(pcmcia_modify_configuration); | ||
473 | |||
474 | |||
475 | int pcmcia_release_configuration(client_handle_t handle) | ||
476 | { | ||
477 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | ||
478 | struct pcmcia_socket *s; | ||
479 | int i; | ||
480 | |||
481 | if (CHECK_HANDLE(handle) || | ||
482 | !(handle->state & CLIENT_CONFIG_LOCKED)) | ||
483 | return CS_BAD_HANDLE; | ||
484 | handle->state &= ~CLIENT_CONFIG_LOCKED; | ||
485 | s = SOCKET(handle); | ||
486 | |||
487 | #ifdef CONFIG_CARDBUS | ||
488 | if (handle->state & CLIENT_CARDBUS) | ||
489 | return CS_SUCCESS; | ||
490 | #endif | ||
491 | |||
492 | if (!(handle->state & CLIENT_STALE)) { | ||
493 | config_t *c = CONFIG(handle); | ||
494 | if (--(s->lock_count) == 0) { | ||
495 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ | ||
496 | s->socket.Vpp = 0; | ||
497 | s->socket.io_irq = 0; | ||
498 | s->ops->set_socket(s, &s->socket); | ||
499 | } | ||
500 | if (c->state & CONFIG_IO_REQ) | ||
501 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
502 | if (s->io[i].NumPorts == 0) | ||
503 | continue; | ||
504 | s->io[i].Config--; | ||
505 | if (s->io[i].Config != 0) | ||
506 | continue; | ||
507 | io.map = i; | ||
508 | s->ops->set_io_map(s, &io); | ||
509 | } | ||
510 | c->state &= ~CONFIG_LOCKED; | ||
511 | } | ||
512 | |||
513 | return CS_SUCCESS; | ||
514 | } /* pcmcia_release_configuration */ | ||
515 | EXPORT_SYMBOL(pcmcia_release_configuration); | ||
516 | |||
517 | |||
518 | /** pcmcia_release_io | ||
519 | * | ||
520 | * Release_io() releases the I/O ranges allocated by a client. This | ||
521 | * may be invoked some time after a card ejection has already dumped | ||
522 | * the actual socket configuration, so if the client is "stale", we | ||
523 | * don't bother checking the port ranges against the current socket | ||
524 | * values. | ||
525 | */ | ||
526 | int pcmcia_release_io(client_handle_t handle, io_req_t *req) | ||
527 | { | ||
528 | struct pcmcia_socket *s; | ||
529 | |||
530 | if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ)) | ||
531 | return CS_BAD_HANDLE; | ||
532 | handle->state &= ~CLIENT_IO_REQ; | ||
533 | s = SOCKET(handle); | ||
534 | |||
535 | #ifdef CONFIG_CARDBUS | ||
536 | if (handle->state & CLIENT_CARDBUS) | ||
537 | return CS_SUCCESS; | ||
538 | #endif | ||
539 | |||
540 | if (!(handle->state & CLIENT_STALE)) { | ||
541 | config_t *c = CONFIG(handle); | ||
542 | if (c->state & CONFIG_LOCKED) | ||
543 | return CS_CONFIGURATION_LOCKED; | ||
544 | if ((c->io.BasePort1 != req->BasePort1) || | ||
545 | (c->io.NumPorts1 != req->NumPorts1) || | ||
546 | (c->io.BasePort2 != req->BasePort2) || | ||
547 | (c->io.NumPorts2 != req->NumPorts2)) | ||
548 | return CS_BAD_ARGS; | ||
549 | c->state &= ~CONFIG_IO_REQ; | ||
550 | } | ||
551 | |||
552 | release_io_space(s, req->BasePort1, req->NumPorts1); | ||
553 | if (req->NumPorts2) | ||
554 | release_io_space(s, req->BasePort2, req->NumPorts2); | ||
555 | |||
556 | return CS_SUCCESS; | ||
557 | } /* pcmcia_release_io */ | ||
558 | EXPORT_SYMBOL(pcmcia_release_io); | ||
559 | |||
560 | |||
561 | int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) | ||
562 | { | ||
563 | struct pcmcia_socket *s; | ||
564 | if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ)) | ||
565 | return CS_BAD_HANDLE; | ||
566 | handle->state &= ~CLIENT_IRQ_REQ; | ||
567 | s = SOCKET(handle); | ||
568 | |||
569 | if (!(handle->state & CLIENT_STALE)) { | ||
570 | config_t *c = CONFIG(handle); | ||
571 | if (c->state & CONFIG_LOCKED) | ||
572 | return CS_CONFIGURATION_LOCKED; | ||
573 | if (c->irq.Attributes != req->Attributes) | ||
574 | return CS_BAD_ATTRIBUTE; | ||
575 | if (s->irq.AssignedIRQ != req->AssignedIRQ) | ||
576 | return CS_BAD_IRQ; | ||
577 | if (--s->irq.Config == 0) { | ||
578 | c->state &= ~CONFIG_IRQ_REQ; | ||
579 | s->irq.AssignedIRQ = 0; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (req->Attributes & IRQ_HANDLE_PRESENT) { | ||
584 | free_irq(req->AssignedIRQ, req->Instance); | ||
585 | } | ||
586 | |||
587 | #ifdef CONFIG_PCMCIA_PROBE | ||
588 | pcmcia_used_irq[req->AssignedIRQ]--; | ||
589 | #endif | ||
590 | |||
591 | return CS_SUCCESS; | ||
592 | } /* pcmcia_release_irq */ | ||
593 | EXPORT_SYMBOL(pcmcia_release_irq); | ||
594 | |||
595 | |||
596 | int pcmcia_release_window(window_handle_t win) | ||
597 | { | ||
598 | struct pcmcia_socket *s; | ||
599 | |||
600 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | ||
601 | return CS_BAD_HANDLE; | ||
602 | s = win->sock; | ||
603 | if (!(win->handle->state & CLIENT_WIN_REQ(win->index))) | ||
604 | return CS_BAD_HANDLE; | ||
605 | |||
606 | /* Shut down memory window */ | ||
607 | win->ctl.flags &= ~MAP_ACTIVE; | ||
608 | s->ops->set_mem_map(s, &win->ctl); | ||
609 | s->state &= ~SOCKET_WIN_REQ(win->index); | ||
610 | |||
611 | /* Release system memory */ | ||
612 | if (win->ctl.res) { | ||
613 | release_resource(win->ctl.res); | ||
614 | kfree(win->ctl.res); | ||
615 | win->ctl.res = NULL; | ||
616 | } | ||
617 | win->handle->state &= ~CLIENT_WIN_REQ(win->index); | ||
618 | |||
619 | win->magic = 0; | ||
620 | |||
621 | return CS_SUCCESS; | ||
622 | } /* pcmcia_release_window */ | ||
623 | EXPORT_SYMBOL(pcmcia_release_window); | ||
624 | |||
625 | |||
626 | int pcmcia_request_configuration(client_handle_t handle, | ||
627 | config_req_t *req) | ||
628 | { | ||
629 | int i; | ||
630 | u_int base; | ||
631 | struct pcmcia_socket *s; | ||
632 | config_t *c; | ||
633 | pccard_io_map iomap; | ||
634 | |||
635 | if (CHECK_HANDLE(handle)) | ||
636 | return CS_BAD_HANDLE; | ||
637 | s = SOCKET(handle); | ||
638 | if (!(s->state & SOCKET_PRESENT)) | ||
639 | return CS_NO_CARD; | ||
640 | |||
641 | #ifdef CONFIG_CARDBUS | ||
642 | if (handle->state & CLIENT_CARDBUS) | ||
643 | return CS_UNSUPPORTED_MODE; | ||
644 | #endif | ||
645 | |||
646 | if (req->IntType & INT_CARDBUS) | ||
647 | return CS_UNSUPPORTED_MODE; | ||
648 | c = CONFIG(handle); | ||
649 | if (c->state & CONFIG_LOCKED) | ||
650 | return CS_CONFIGURATION_LOCKED; | ||
651 | |||
652 | /* Do power control. We don't allow changes in Vcc. */ | ||
653 | if (s->socket.Vcc != req->Vcc) | ||
654 | return CS_BAD_VCC; | ||
655 | if (req->Vpp1 != req->Vpp2) | ||
656 | return CS_BAD_VPP; | ||
657 | s->socket.Vpp = req->Vpp1; | ||
658 | if (s->ops->set_socket(s, &s->socket)) | ||
659 | return CS_BAD_VPP; | ||
660 | |||
661 | c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1; | ||
662 | |||
663 | /* Pick memory or I/O card, DMA mode, interrupt */ | ||
664 | c->IntType = req->IntType; | ||
665 | c->Attributes = req->Attributes; | ||
666 | if (req->IntType & INT_MEMORY_AND_IO) | ||
667 | s->socket.flags |= SS_IOCARD; | ||
668 | if (req->IntType & INT_ZOOMED_VIDEO) | ||
669 | s->socket.flags |= SS_ZVCARD | SS_IOCARD; | ||
670 | if (req->Attributes & CONF_ENABLE_DMA) | ||
671 | s->socket.flags |= SS_DMA_MODE; | ||
672 | if (req->Attributes & CONF_ENABLE_SPKR) | ||
673 | s->socket.flags |= SS_SPKR_ENA; | ||
674 | if (req->Attributes & CONF_ENABLE_IRQ) | ||
675 | s->socket.io_irq = s->irq.AssignedIRQ; | ||
676 | else | ||
677 | s->socket.io_irq = 0; | ||
678 | s->ops->set_socket(s, &s->socket); | ||
679 | s->lock_count++; | ||
680 | |||
681 | /* Set up CIS configuration registers */ | ||
682 | base = c->ConfigBase = req->ConfigBase; | ||
683 | c->Present = c->CardValues = req->Present; | ||
684 | if (req->Present & PRESENT_COPY) { | ||
685 | c->Copy = req->Copy; | ||
686 | pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); | ||
687 | } | ||
688 | if (req->Present & PRESENT_OPTION) { | ||
689 | if (s->functions == 1) { | ||
690 | c->Option = req->ConfigIndex & COR_CONFIG_MASK; | ||
691 | } else { | ||
692 | c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; | ||
693 | c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; | ||
694 | if (req->Present & PRESENT_IOBASE_0) | ||
695 | c->Option |= COR_ADDR_DECODE; | ||
696 | } | ||
697 | if (c->state & CONFIG_IRQ_REQ) | ||
698 | if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) | ||
699 | c->Option |= COR_LEVEL_REQ; | ||
700 | pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); | ||
701 | mdelay(40); | ||
702 | } | ||
703 | if (req->Present & PRESENT_STATUS) { | ||
704 | c->Status = req->Status; | ||
705 | pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); | ||
706 | } | ||
707 | if (req->Present & PRESENT_PIN_REPLACE) { | ||
708 | c->Pin = req->Pin; | ||
709 | pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); | ||
710 | } | ||
711 | if (req->Present & PRESENT_EXT_STATUS) { | ||
712 | c->ExtStatus = req->ExtStatus; | ||
713 | pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); | ||
714 | } | ||
715 | if (req->Present & PRESENT_IOBASE_0) { | ||
716 | u_char b = c->io.BasePort1 & 0xff; | ||
717 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); | ||
718 | b = (c->io.BasePort1 >> 8) & 0xff; | ||
719 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); | ||
720 | } | ||
721 | if (req->Present & PRESENT_IOSIZE) { | ||
722 | u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1; | ||
723 | pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); | ||
724 | } | ||
725 | |||
726 | /* Configure I/O windows */ | ||
727 | if (c->state & CONFIG_IO_REQ) { | ||
728 | iomap.speed = io_speed; | ||
729 | for (i = 0; i < MAX_IO_WIN; i++) | ||
730 | if (s->io[i].NumPorts != 0) { | ||
731 | iomap.map = i; | ||
732 | iomap.flags = MAP_ACTIVE; | ||
733 | switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) { | ||
734 | case IO_DATA_PATH_WIDTH_16: | ||
735 | iomap.flags |= MAP_16BIT; break; | ||
736 | case IO_DATA_PATH_WIDTH_AUTO: | ||
737 | iomap.flags |= MAP_AUTOSZ; break; | ||
738 | default: | ||
739 | break; | ||
740 | } | ||
741 | iomap.start = s->io[i].BasePort; | ||
742 | iomap.stop = iomap.start + s->io[i].NumPorts - 1; | ||
743 | s->ops->set_io_map(s, &iomap); | ||
744 | s->io[i].Config++; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | c->state |= CONFIG_LOCKED; | ||
749 | handle->state |= CLIENT_CONFIG_LOCKED; | ||
750 | return CS_SUCCESS; | ||
751 | } /* pcmcia_request_configuration */ | ||
752 | EXPORT_SYMBOL(pcmcia_request_configuration); | ||
753 | |||
754 | |||
755 | /** pcmcia_request_io | ||
756 | * | ||
757 | * Request_io() reserves ranges of port addresses for a socket. | ||
758 | * I have not implemented range sharing or alias addressing. | ||
759 | */ | ||
760 | int pcmcia_request_io(client_handle_t handle, io_req_t *req) | ||
761 | { | ||
762 | struct pcmcia_socket *s; | ||
763 | config_t *c; | ||
764 | |||
765 | if (CHECK_HANDLE(handle)) | ||
766 | return CS_BAD_HANDLE; | ||
767 | s = SOCKET(handle); | ||
768 | if (!(s->state & SOCKET_PRESENT)) | ||
769 | return CS_NO_CARD; | ||
770 | |||
771 | if (handle->state & CLIENT_CARDBUS) { | ||
772 | #ifdef CONFIG_CARDBUS | ||
773 | handle->state |= CLIENT_IO_REQ; | ||
774 | return CS_SUCCESS; | ||
775 | #else | ||
776 | return CS_UNSUPPORTED_FUNCTION; | ||
777 | #endif | ||
778 | } | ||
779 | |||
780 | if (!req) | ||
781 | return CS_UNSUPPORTED_MODE; | ||
782 | c = CONFIG(handle); | ||
783 | if (c->state & CONFIG_LOCKED) | ||
784 | return CS_CONFIGURATION_LOCKED; | ||
785 | if (c->state & CONFIG_IO_REQ) | ||
786 | return CS_IN_USE; | ||
787 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) | ||
788 | return CS_BAD_ATTRIBUTE; | ||
789 | if ((req->NumPorts2 > 0) && | ||
790 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) | ||
791 | return CS_BAD_ATTRIBUTE; | ||
792 | |||
793 | if (alloc_io_space(s, req->Attributes1, &req->BasePort1, | ||
794 | req->NumPorts1, req->IOAddrLines)) | ||
795 | return CS_IN_USE; | ||
796 | |||
797 | if (req->NumPorts2) { | ||
798 | if (alloc_io_space(s, req->Attributes2, &req->BasePort2, | ||
799 | req->NumPorts2, req->IOAddrLines)) { | ||
800 | release_io_space(s, req->BasePort1, req->NumPorts1); | ||
801 | return CS_IN_USE; | ||
802 | } | ||
803 | } | ||
804 | |||
805 | c->io = *req; | ||
806 | c->state |= CONFIG_IO_REQ; | ||
807 | handle->state |= CLIENT_IO_REQ; | ||
808 | return CS_SUCCESS; | ||
809 | } /* pcmcia_request_io */ | ||
810 | EXPORT_SYMBOL(pcmcia_request_io); | ||
811 | |||
812 | |||
813 | /** pcmcia_request_irq | ||
814 | * | ||
815 | * Request_irq() reserves an irq for this client. | ||
816 | * | ||
817 | * Also, since Linux only reserves irq's when they are actually | ||
818 | * hooked, we don't guarantee that an irq will still be available | ||
819 | * when the configuration is locked. Now that I think about it, | ||
820 | * there might be a way to fix this using a dummy handler. | ||
821 | */ | ||
822 | |||
823 | #ifdef CONFIG_PCMCIA_PROBE | ||
824 | static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
825 | { | ||
826 | return IRQ_NONE; | ||
827 | } | ||
828 | #endif | ||
829 | |||
830 | int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) | ||
831 | { | ||
832 | struct pcmcia_socket *s; | ||
833 | config_t *c; | ||
834 | int ret = CS_IN_USE, irq = 0; | ||
835 | struct pcmcia_device *p_dev = handle_to_pdev(handle); | ||
836 | |||
837 | if (CHECK_HANDLE(handle)) | ||
838 | return CS_BAD_HANDLE; | ||
839 | s = SOCKET(handle); | ||
840 | if (!(s->state & SOCKET_PRESENT)) | ||
841 | return CS_NO_CARD; | ||
842 | c = CONFIG(handle); | ||
843 | if (c->state & CONFIG_LOCKED) | ||
844 | return CS_CONFIGURATION_LOCKED; | ||
845 | if (c->state & CONFIG_IRQ_REQ) | ||
846 | return CS_IN_USE; | ||
847 | |||
848 | #ifdef CONFIG_PCMCIA_PROBE | ||
849 | if (s->irq.AssignedIRQ != 0) { | ||
850 | /* If the interrupt is already assigned, it must be the same */ | ||
851 | irq = s->irq.AssignedIRQ; | ||
852 | } else { | ||
853 | int try; | ||
854 | u32 mask = s->irq_mask; | ||
855 | void *data = NULL; | ||
856 | |||
857 | for (try = 0; try < 64; try++) { | ||
858 | irq = try % 32; | ||
859 | |||
860 | /* marked as available by driver, and not blocked by userspace? */ | ||
861 | if (!((mask >> irq) & 1)) | ||
862 | continue; | ||
863 | |||
864 | /* avoid an IRQ which is already used by a PCMCIA card */ | ||
865 | if ((try < 32) && pcmcia_used_irq[irq]) | ||
866 | continue; | ||
867 | |||
868 | /* register the correct driver, if possible, of check whether | ||
869 | * registering a dummy handle works, i.e. if the IRQ isn't | ||
870 | * marked as used by the kernel resource management core */ | ||
871 | ret = request_irq(irq, | ||
872 | (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, | ||
873 | ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || | ||
874 | (s->functions > 1) || | ||
875 | (irq == s->pci_irq)) ? SA_SHIRQ : 0, | ||
876 | p_dev->dev.bus_id, | ||
877 | (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); | ||
878 | if (!ret) { | ||
879 | if (!(req->Attributes & IRQ_HANDLE_PRESENT)) | ||
880 | free_irq(irq, data); | ||
881 | break; | ||
882 | } | ||
883 | } | ||
884 | } | ||
885 | #endif | ||
886 | if (ret) { | ||
887 | if (!s->pci_irq) | ||
888 | return ret; | ||
889 | irq = s->pci_irq; | ||
890 | } | ||
891 | |||
892 | if (ret && req->Attributes & IRQ_HANDLE_PRESENT) { | ||
893 | if (request_irq(irq, req->Handler, | ||
894 | ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || | ||
895 | (s->functions > 1) || | ||
896 | (irq == s->pci_irq)) ? SA_SHIRQ : 0, | ||
897 | p_dev->dev.bus_id, req->Instance)) | ||
898 | return CS_IN_USE; | ||
899 | } | ||
900 | |||
901 | c->irq.Attributes = req->Attributes; | ||
902 | s->irq.AssignedIRQ = req->AssignedIRQ = irq; | ||
903 | s->irq.Config++; | ||
904 | |||
905 | c->state |= CONFIG_IRQ_REQ; | ||
906 | handle->state |= CLIENT_IRQ_REQ; | ||
907 | |||
908 | #ifdef CONFIG_PCMCIA_PROBE | ||
909 | pcmcia_used_irq[irq]++; | ||
910 | #endif | ||
911 | |||
912 | return CS_SUCCESS; | ||
913 | } /* pcmcia_request_irq */ | ||
914 | EXPORT_SYMBOL(pcmcia_request_irq); | ||
915 | |||
916 | |||
917 | /** pcmcia_request_window | ||
918 | * | ||
919 | * Request_window() establishes a mapping between card memory space | ||
920 | * and system memory space. | ||
921 | */ | ||
922 | int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh) | ||
923 | { | ||
924 | struct pcmcia_socket *s; | ||
925 | window_t *win; | ||
926 | u_long align; | ||
927 | int w; | ||
928 | |||
929 | if (CHECK_HANDLE(*handle)) | ||
930 | return CS_BAD_HANDLE; | ||
931 | s = (*handle)->Socket; | ||
932 | if (!(s->state & SOCKET_PRESENT)) | ||
933 | return CS_NO_CARD; | ||
934 | if (req->Attributes & (WIN_PAGED | WIN_SHARED)) | ||
935 | return CS_BAD_ATTRIBUTE; | ||
936 | |||
937 | /* Window size defaults to smallest available */ | ||
938 | if (req->Size == 0) | ||
939 | req->Size = s->map_size; | ||
940 | align = (((s->features & SS_CAP_MEM_ALIGN) || | ||
941 | (req->Attributes & WIN_STRICT_ALIGN)) ? | ||
942 | req->Size : s->map_size); | ||
943 | if (req->Size & (s->map_size-1)) | ||
944 | return CS_BAD_SIZE; | ||
945 | if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || | ||
946 | (req->Base & (align-1))) | ||
947 | return CS_BAD_BASE; | ||
948 | if (req->Base) | ||
949 | align = 0; | ||
950 | |||
951 | /* Allocate system memory window */ | ||
952 | for (w = 0; w < MAX_WIN; w++) | ||
953 | if (!(s->state & SOCKET_WIN_REQ(w))) break; | ||
954 | if (w == MAX_WIN) | ||
955 | return CS_OUT_OF_RESOURCE; | ||
956 | |||
957 | win = &s->win[w]; | ||
958 | win->magic = WINDOW_MAGIC; | ||
959 | win->index = w; | ||
960 | win->handle = *handle; | ||
961 | win->sock = s; | ||
962 | |||
963 | if (!(s->features & SS_CAP_STATIC_MAP)) { | ||
964 | win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align, | ||
965 | (req->Attributes & WIN_MAP_BELOW_1MB), s); | ||
966 | if (!win->ctl.res) | ||
967 | return CS_IN_USE; | ||
968 | } | ||
969 | (*handle)->state |= CLIENT_WIN_REQ(w); | ||
970 | |||
971 | /* Configure the socket controller */ | ||
972 | win->ctl.map = w+1; | ||
973 | win->ctl.flags = 0; | ||
974 | win->ctl.speed = req->AccessSpeed; | ||
975 | if (req->Attributes & WIN_MEMORY_TYPE) | ||
976 | win->ctl.flags |= MAP_ATTRIB; | ||
977 | if (req->Attributes & WIN_ENABLE) | ||
978 | win->ctl.flags |= MAP_ACTIVE; | ||
979 | if (req->Attributes & WIN_DATA_WIDTH_16) | ||
980 | win->ctl.flags |= MAP_16BIT; | ||
981 | if (req->Attributes & WIN_USE_WAIT) | ||
982 | win->ctl.flags |= MAP_USE_WAIT; | ||
983 | win->ctl.card_start = 0; | ||
984 | if (s->ops->set_mem_map(s, &win->ctl) != 0) | ||
985 | return CS_BAD_ARGS; | ||
986 | s->state |= SOCKET_WIN_REQ(w); | ||
987 | |||
988 | /* Return window handle */ | ||
989 | if (s->features & SS_CAP_STATIC_MAP) { | ||
990 | req->Base = win->ctl.static_start; | ||
991 | } else { | ||
992 | req->Base = win->ctl.res->start; | ||
993 | } | ||
994 | *wh = win; | ||
995 | |||
996 | return CS_SUCCESS; | ||
997 | } /* pcmcia_request_window */ | ||
998 | EXPORT_SYMBOL(pcmcia_request_window); | ||
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index b6843f8d300d..0668384ebc8b 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -72,7 +72,7 @@ int pcmcia_adjust_resource_info(adjust_t *adj) | |||
72 | /* you can't use the old interface if the new | 72 | /* you can't use the old interface if the new |
73 | * one was used before */ | 73 | * one was used before */ |
74 | spin_lock_irqsave(&s->lock, flags); | 74 | spin_lock_irqsave(&s->lock, flags); |
75 | if ((s->resource_setup_done) && | 75 | if ((s->resource_setup_new) && |
76 | !(s->resource_setup_old)) { | 76 | !(s->resource_setup_old)) { |
77 | spin_unlock_irqrestore(&s->lock, flags); | 77 | spin_unlock_irqrestore(&s->lock, flags); |
78 | continue; | 78 | continue; |
@@ -105,29 +105,32 @@ void pcmcia_validate_mem(struct pcmcia_socket *s) | |||
105 | } | 105 | } |
106 | EXPORT_SYMBOL(pcmcia_validate_mem); | 106 | EXPORT_SYMBOL(pcmcia_validate_mem); |
107 | 107 | ||
108 | int adjust_io_region(struct resource *res, unsigned long r_start, | 108 | int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start, |
109 | unsigned long r_end, struct pcmcia_socket *s) | 109 | unsigned long r_end, struct pcmcia_socket *s) |
110 | { | 110 | { |
111 | if (s->resource_ops->adjust_io_region) | 111 | if (s->resource_ops->adjust_io_region) |
112 | return s->resource_ops->adjust_io_region(res, r_start, r_end, s); | 112 | return s->resource_ops->adjust_io_region(res, r_start, r_end, s); |
113 | return -ENOMEM; | 113 | return -ENOMEM; |
114 | } | 114 | } |
115 | EXPORT_SYMBOL(pcmcia_adjust_io_region); | ||
115 | 116 | ||
116 | struct resource *find_io_region(unsigned long base, int num, | 117 | struct resource *pcmcia_find_io_region(unsigned long base, int num, |
117 | unsigned long align, struct pcmcia_socket *s) | 118 | unsigned long align, struct pcmcia_socket *s) |
118 | { | 119 | { |
119 | if (s->resource_ops->find_io) | 120 | if (s->resource_ops->find_io) |
120 | return s->resource_ops->find_io(base, num, align, s); | 121 | return s->resource_ops->find_io(base, num, align, s); |
121 | return NULL; | 122 | return NULL; |
122 | } | 123 | } |
124 | EXPORT_SYMBOL(pcmcia_find_io_region); | ||
123 | 125 | ||
124 | struct resource *find_mem_region(u_long base, u_long num, u_long align, | 126 | struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, |
125 | int low, struct pcmcia_socket *s) | 127 | int low, struct pcmcia_socket *s) |
126 | { | 128 | { |
127 | if (s->resource_ops->find_mem) | 129 | if (s->resource_ops->find_mem) |
128 | return s->resource_ops->find_mem(base, num, align, low, s); | 130 | return s->resource_ops->find_mem(base, num, align, low, s); |
129 | return NULL; | 131 | return NULL; |
130 | } | 132 | } |
133 | EXPORT_SYMBOL(pcmcia_find_mem_region); | ||
131 | 134 | ||
132 | void release_resource_db(struct pcmcia_socket *s) | 135 | void release_resource_db(struct pcmcia_socket *s) |
133 | { | 136 | { |
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 5876bab7c14c..c42455d20eb6 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -372,6 +372,9 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) | |||
372 | base, base+num-1); | 372 | base, base+num-1); |
373 | bad = fail = 0; | 373 | bad = fail = 0; |
374 | step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); | 374 | step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); |
375 | /* don't allow too large steps */ | ||
376 | if (step > 0x800000) | ||
377 | step = 0x800000; | ||
375 | /* cis_readable wants to map 2x map_size */ | 378 | /* cis_readable wants to map 2x map_size */ |
376 | if (step < 2 * s->map_size) | 379 | if (step < 2 * s->map_size) |
377 | step = 2 * s->map_size; | 380 | step = 2 * s->map_size; |
@@ -465,8 +468,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) | |||
465 | 468 | ||
466 | for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { | 469 | for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { |
467 | mm = *m; | 470 | mm = *m; |
468 | if (do_mem_probe(mm.base, mm.num, s)) | 471 | do_mem_probe(mm.base, mm.num, s); |
469 | break; | ||
470 | } | 472 | } |
471 | } | 473 | } |
472 | 474 | ||
@@ -601,7 +603,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
601 | 603 | ||
602 | ======================================================================*/ | 604 | ======================================================================*/ |
603 | 605 | ||
604 | struct resource *nonstatic_find_io_region(unsigned long base, int num, | 606 | static struct resource *nonstatic_find_io_region(unsigned long base, int num, |
605 | unsigned long align, struct pcmcia_socket *s) | 607 | unsigned long align, struct pcmcia_socket *s) |
606 | { | 608 | { |
607 | struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id); | 609 | struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id); |
@@ -635,8 +637,8 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
635 | return res; | 637 | return res; |
636 | } | 638 | } |
637 | 639 | ||
638 | struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align, | 640 | static struct resource * nonstatic_find_mem_region(u_long base, u_long num, |
639 | int low, struct pcmcia_socket *s) | 641 | u_long align, int low, struct pcmcia_socket *s) |
640 | { | 642 | { |
641 | struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id); | 643 | struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id); |
642 | struct socket_data *s_data = s->resource_data; | 644 | struct socket_data *s_data = s->resource_data; |
@@ -683,27 +685,23 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig | |||
683 | } | 685 | } |
684 | 686 | ||
685 | 687 | ||
686 | static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) | 688 | static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end) |
687 | { | 689 | { |
688 | u_long base, num; | ||
689 | struct socket_data *data = s->resource_data; | 690 | struct socket_data *data = s->resource_data; |
690 | int ret; | 691 | unsigned long size = end - start + 1; |
691 | 692 | int ret = 0; | |
692 | base = adj->resource.memory.Base; | ||
693 | num = adj->resource.memory.Size; | ||
694 | if ((num == 0) || (base+num-1 < base)) | ||
695 | return CS_BAD_SIZE; | ||
696 | 693 | ||
697 | ret = CS_SUCCESS; | 694 | if (end <= start) |
695 | return -EINVAL; | ||
698 | 696 | ||
699 | down(&rsrc_sem); | 697 | down(&rsrc_sem); |
700 | switch (adj->Action) { | 698 | switch (action) { |
701 | case ADD_MANAGED_RESOURCE: | 699 | case ADD_MANAGED_RESOURCE: |
702 | ret = add_interval(&data->mem_db, base, num); | 700 | ret = add_interval(&data->mem_db, start, size); |
703 | break; | 701 | break; |
704 | case REMOVE_MANAGED_RESOURCE: | 702 | case REMOVE_MANAGED_RESOURCE: |
705 | ret = sub_interval(&data->mem_db, base, num); | 703 | ret = sub_interval(&data->mem_db, start, size); |
706 | if (ret == CS_SUCCESS) { | 704 | if (!ret) { |
707 | struct pcmcia_socket *socket; | 705 | struct pcmcia_socket *socket; |
708 | down_read(&pcmcia_socket_list_rwsem); | 706 | down_read(&pcmcia_socket_list_rwsem); |
709 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) | 707 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) |
@@ -712,7 +710,7 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) | |||
712 | } | 710 | } |
713 | break; | 711 | break; |
714 | default: | 712 | default: |
715 | ret = CS_UNSUPPORTED_FUNCTION; | 713 | ret = -EINVAL; |
716 | } | 714 | } |
717 | up(&rsrc_sem); | 715 | up(&rsrc_sem); |
718 | 716 | ||
@@ -720,36 +718,35 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) | |||
720 | } | 718 | } |
721 | 719 | ||
722 | 720 | ||
723 | static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) | 721 | static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end) |
724 | { | 722 | { |
725 | struct socket_data *data = s->resource_data; | 723 | struct socket_data *data = s->resource_data; |
726 | kio_addr_t base, num; | 724 | unsigned long size = end - start + 1; |
727 | int ret = CS_SUCCESS; | 725 | int ret = 0; |
728 | 726 | ||
729 | base = adj->resource.io.BasePort; | 727 | if (end <= start) |
730 | num = adj->resource.io.NumPorts; | 728 | return -EINVAL; |
731 | if ((base < 0) || (base > 0xffff)) | 729 | |
732 | return CS_BAD_BASE; | 730 | if (end > IO_SPACE_LIMIT) |
733 | if ((num <= 0) || (base+num > 0x10000) || (base+num <= base)) | 731 | return -EINVAL; |
734 | return CS_BAD_SIZE; | ||
735 | 732 | ||
736 | down(&rsrc_sem); | 733 | down(&rsrc_sem); |
737 | switch (adj->Action) { | 734 | switch (action) { |
738 | case ADD_MANAGED_RESOURCE: | 735 | case ADD_MANAGED_RESOURCE: |
739 | if (add_interval(&data->io_db, base, num) != 0) { | 736 | if (add_interval(&data->io_db, start, size) != 0) { |
740 | ret = CS_IN_USE; | 737 | ret = -EBUSY; |
741 | break; | 738 | break; |
742 | } | 739 | } |
743 | #ifdef CONFIG_PCMCIA_PROBE | 740 | #ifdef CONFIG_PCMCIA_PROBE |
744 | if (probe_io) | 741 | if (probe_io) |
745 | do_io_probe(s, base, num); | 742 | do_io_probe(s, start, size); |
746 | #endif | 743 | #endif |
747 | break; | 744 | break; |
748 | case REMOVE_MANAGED_RESOURCE: | 745 | case REMOVE_MANAGED_RESOURCE: |
749 | sub_interval(&data->io_db, base, num); | 746 | sub_interval(&data->io_db, start, size); |
750 | break; | 747 | break; |
751 | default: | 748 | default: |
752 | ret = CS_UNSUPPORTED_FUNCTION; | 749 | ret = -EINVAL; |
753 | break; | 750 | break; |
754 | } | 751 | } |
755 | up(&rsrc_sem); | 752 | up(&rsrc_sem); |
@@ -760,15 +757,82 @@ static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) | |||
760 | 757 | ||
761 | static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj) | 758 | static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj) |
762 | { | 759 | { |
760 | unsigned long end; | ||
761 | |||
763 | switch (adj->Resource) { | 762 | switch (adj->Resource) { |
764 | case RES_MEMORY_RANGE: | 763 | case RES_MEMORY_RANGE: |
765 | return adjust_memory(s, adj); | 764 | end = adj->resource.memory.Base + adj->resource.memory.Size - 1; |
765 | return adjust_memory(s, adj->Action, adj->resource.memory.Base, end); | ||
766 | case RES_IO_RANGE: | 766 | case RES_IO_RANGE: |
767 | return adjust_io(s, adj); | 767 | end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1; |
768 | return adjust_io(s, adj->Action, adj->resource.io.BasePort, end); | ||
768 | } | 769 | } |
769 | return CS_UNSUPPORTED_FUNCTION; | 770 | return CS_UNSUPPORTED_FUNCTION; |
770 | } | 771 | } |
771 | 772 | ||
773 | #ifdef CONFIG_PCI | ||
774 | static int nonstatic_autoadd_resources(struct pcmcia_socket *s) | ||
775 | { | ||
776 | struct resource *res; | ||
777 | int i, done = 0; | ||
778 | |||
779 | if (!s->cb_dev || !s->cb_dev->bus) | ||
780 | return -ENODEV; | ||
781 | |||
782 | #if defined(CONFIG_X86) || defined(CONFIG_X86_64) | ||
783 | /* If this is the root bus, the risk of hitting | ||
784 | * some strange system devices which aren't protected | ||
785 | * by either ACPI resource tables or properly requested | ||
786 | * resources is too big. Therefore, don't do auto-adding | ||
787 | * of resources at the moment. | ||
788 | */ | ||
789 | if (s->cb_dev->bus->number == 0) | ||
790 | return -EINVAL; | ||
791 | #endif | ||
792 | |||
793 | for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) { | ||
794 | res = s->cb_dev->bus->resource[i]; | ||
795 | if (!res) | ||
796 | continue; | ||
797 | |||
798 | if (res->flags & IORESOURCE_IO) { | ||
799 | if (res == &ioport_resource) | ||
800 | continue; | ||
801 | printk(KERN_INFO "pcmcia: parent PCI bridge I/O window: 0x%lx - 0x%lx\n", | ||
802 | res->start, res->end); | ||
803 | if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end)) | ||
804 | done |= IORESOURCE_IO; | ||
805 | |||
806 | } | ||
807 | |||
808 | if (res->flags & IORESOURCE_MEM) { | ||
809 | if (res == &iomem_resource) | ||
810 | continue; | ||
811 | printk(KERN_INFO "pcmcia: parent PCI bridge Memory window: 0x%lx - 0x%lx\n", | ||
812 | res->start, res->end); | ||
813 | if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end)) | ||
814 | done |= IORESOURCE_MEM; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | /* if we got at least one of IO, and one of MEM, we can be glad and | ||
819 | * activate the PCMCIA subsystem */ | ||
820 | if (done & (IORESOURCE_MEM | IORESOURCE_IO)) | ||
821 | s->resource_setup_done = 1; | ||
822 | |||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | #else | ||
827 | |||
828 | static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s) | ||
829 | { | ||
830 | return -ENODEV; | ||
831 | } | ||
832 | |||
833 | #endif | ||
834 | |||
835 | |||
772 | static int nonstatic_init(struct pcmcia_socket *s) | 836 | static int nonstatic_init(struct pcmcia_socket *s) |
773 | { | 837 | { |
774 | struct socket_data *data; | 838 | struct socket_data *data; |
@@ -783,6 +847,8 @@ static int nonstatic_init(struct pcmcia_socket *s) | |||
783 | 847 | ||
784 | s->resource_data = (void *) data; | 848 | s->resource_data = (void *) data; |
785 | 849 | ||
850 | nonstatic_autoadd_resources(s); | ||
851 | |||
786 | return 0; | 852 | return 0; |
787 | } | 853 | } |
788 | 854 | ||
@@ -845,17 +911,16 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size | |||
845 | { | 911 | { |
846 | struct pcmcia_socket *s = class_get_devdata(class_dev); | 912 | struct pcmcia_socket *s = class_get_devdata(class_dev); |
847 | unsigned long start_addr, end_addr; | 913 | unsigned long start_addr, end_addr; |
848 | unsigned int add = 1; | 914 | unsigned int add = ADD_MANAGED_RESOURCE; |
849 | adjust_t adj; | ||
850 | ssize_t ret = 0; | 915 | ssize_t ret = 0; |
851 | 916 | ||
852 | ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); | 917 | ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); |
853 | if (ret != 2) { | 918 | if (ret != 2) { |
854 | ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); | 919 | ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); |
855 | add = 0; | 920 | add = REMOVE_MANAGED_RESOURCE; |
856 | if (ret != 2) { | 921 | if (ret != 2) { |
857 | ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); | 922 | ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); |
858 | add = 1; | 923 | add = ADD_MANAGED_RESOURCE; |
859 | if (ret != 2) | 924 | if (ret != 2) |
860 | return -EINVAL; | 925 | return -EINVAL; |
861 | } | 926 | } |
@@ -863,12 +928,9 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size | |||
863 | if (end_addr <= start_addr) | 928 | if (end_addr <= start_addr) |
864 | return -EINVAL; | 929 | return -EINVAL; |
865 | 930 | ||
866 | adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE; | 931 | ret = adjust_io(s, add, start_addr, end_addr); |
867 | adj.Resource = RES_IO_RANGE; | 932 | if (!ret) |
868 | adj.resource.io.BasePort = start_addr; | 933 | s->resource_setup_new = 1; |
869 | adj.resource.io.NumPorts = end_addr - start_addr + 1; | ||
870 | |||
871 | ret = adjust_io(s, &adj); | ||
872 | 934 | ||
873 | return ret ? ret : count; | 935 | return ret ? ret : count; |
874 | } | 936 | } |
@@ -901,17 +963,16 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz | |||
901 | { | 963 | { |
902 | struct pcmcia_socket *s = class_get_devdata(class_dev); | 964 | struct pcmcia_socket *s = class_get_devdata(class_dev); |
903 | unsigned long start_addr, end_addr; | 965 | unsigned long start_addr, end_addr; |
904 | unsigned int add = 1; | 966 | unsigned int add = ADD_MANAGED_RESOURCE; |
905 | adjust_t adj; | ||
906 | ssize_t ret = 0; | 967 | ssize_t ret = 0; |
907 | 968 | ||
908 | ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); | 969 | ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); |
909 | if (ret != 2) { | 970 | if (ret != 2) { |
910 | ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); | 971 | ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); |
911 | add = 0; | 972 | add = REMOVE_MANAGED_RESOURCE; |
912 | if (ret != 2) { | 973 | if (ret != 2) { |
913 | ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); | 974 | ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); |
914 | add = 1; | 975 | add = ADD_MANAGED_RESOURCE; |
915 | if (ret != 2) | 976 | if (ret != 2) |
916 | return -EINVAL; | 977 | return -EINVAL; |
917 | } | 978 | } |
@@ -919,12 +980,9 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz | |||
919 | if (end_addr <= start_addr) | 980 | if (end_addr <= start_addr) |
920 | return -EINVAL; | 981 | return -EINVAL; |
921 | 982 | ||
922 | adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE; | 983 | ret = adjust_memory(s, add, start_addr, end_addr); |
923 | adj.Resource = RES_MEMORY_RANGE; | 984 | if (!ret) |
924 | adj.resource.memory.Base = start_addr; | 985 | s->resource_setup_new = 1; |
925 | adj.resource.memory.Size = end_addr - start_addr + 1; | ||
926 | |||
927 | ret = adjust_memory(s, &adj); | ||
928 | 986 | ||
929 | return ret ? ret : count; | 987 | return ret ? ret : count; |
930 | } | 988 | } |
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 8eed03938214..fcef54c1c2da 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
@@ -163,28 +163,164 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, | |||
163 | return -EINVAL; | 163 | return -EINVAL; |
164 | 164 | ||
165 | spin_lock_irqsave(&s->lock, flags); | 165 | spin_lock_irqsave(&s->lock, flags); |
166 | if (!s->resource_setup_done) { | 166 | if (!s->resource_setup_done) |
167 | s->resource_setup_done = 1; | 167 | s->resource_setup_done = 1; |
168 | spin_unlock_irqrestore(&s->lock, flags); | 168 | spin_unlock_irqrestore(&s->lock, flags); |
169 | |||
170 | down(&s->skt_sem); | ||
171 | if ((s->callback) && | ||
172 | (s->state & SOCKET_PRESENT) && | ||
173 | !(s->state & SOCKET_CARDBUS)) { | ||
174 | if (try_module_get(s->callback->owner)) { | ||
175 | s->callback->requery(s); | ||
176 | module_put(s->callback->owner); | ||
177 | } | ||
178 | } | ||
179 | up(&s->skt_sem); | ||
180 | |||
181 | return count; | ||
182 | } | ||
183 | static CLASS_DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); | ||
184 | |||
185 | |||
186 | static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off, size_t count) | ||
187 | { | ||
188 | tuple_t tuple; | ||
189 | int status, i; | ||
190 | loff_t pointer = 0; | ||
191 | ssize_t ret = 0; | ||
192 | u_char *tuplebuffer; | ||
193 | u_char *tempbuffer; | ||
194 | |||
195 | tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL); | ||
196 | if (!tuplebuffer) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL); | ||
200 | if (!tempbuffer) { | ||
201 | ret = -ENOMEM; | ||
202 | goto free_tuple; | ||
203 | } | ||
204 | |||
205 | memset(&tuple, 0, sizeof(tuple_t)); | ||
206 | |||
207 | tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON; | ||
208 | tuple.DesiredTuple = RETURN_FIRST_TUPLE; | ||
209 | tuple.TupleOffset = 0; | ||
210 | |||
211 | status = pccard_get_first_tuple(s, BIND_FN_ALL, &tuple); | ||
212 | while (!status) { | ||
213 | tuple.TupleData = tuplebuffer; | ||
214 | tuple.TupleDataMax = 255; | ||
215 | memset(tuplebuffer, 0, sizeof(u_char) * 255); | ||
169 | 216 | ||
217 | status = pccard_get_tuple_data(s, &tuple); | ||
218 | if (status) | ||
219 | break; | ||
220 | |||
221 | if (off < (pointer + 2 + tuple.TupleDataLen)) { | ||
222 | tempbuffer[0] = tuple.TupleCode & 0xff; | ||
223 | tempbuffer[1] = tuple.TupleLink & 0xff; | ||
224 | for (i = 0; i < tuple.TupleDataLen; i++) | ||
225 | tempbuffer[i + 2] = tuplebuffer[i] & 0xff; | ||
226 | |||
227 | for (i = 0; i < (2 + tuple.TupleDataLen); i++) { | ||
228 | if (((i + pointer) >= off) && | ||
229 | (i + pointer) < (off + count)) { | ||
230 | buf[ret] = tempbuffer[i]; | ||
231 | ret++; | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | pointer += 2 + tuple.TupleDataLen; | ||
237 | |||
238 | if (pointer >= (off + count)) | ||
239 | break; | ||
240 | |||
241 | if (tuple.TupleCode == CISTPL_END) | ||
242 | break; | ||
243 | status = pccard_get_next_tuple(s, BIND_FN_ALL, &tuple); | ||
244 | } | ||
245 | |||
246 | kfree(tempbuffer); | ||
247 | free_tuple: | ||
248 | kfree(tuplebuffer); | ||
249 | |||
250 | return (ret); | ||
251 | } | ||
252 | |||
253 | static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) | ||
254 | { | ||
255 | unsigned int size = 0x200; | ||
256 | |||
257 | if (off >= size) | ||
258 | count = 0; | ||
259 | else { | ||
260 | struct pcmcia_socket *s; | ||
261 | cisinfo_t cisinfo; | ||
262 | |||
263 | if (off + count > size) | ||
264 | count = size - off; | ||
265 | |||
266 | s = to_socket(container_of(kobj, struct class_device, kobj)); | ||
267 | |||
268 | if (!(s->state & SOCKET_PRESENT)) | ||
269 | return -ENODEV; | ||
270 | if (pccard_validate_cis(s, BIND_FN_ALL, &cisinfo)) | ||
271 | return -EIO; | ||
272 | if (!cisinfo.Chains) | ||
273 | return -ENODATA; | ||
274 | |||
275 | count = pccard_extract_cis(s, buf, off, count); | ||
276 | } | ||
277 | |||
278 | return (count); | ||
279 | } | ||
280 | |||
281 | static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) | ||
282 | { | ||
283 | struct pcmcia_socket *s = to_socket(container_of(kobj, struct class_device, kobj)); | ||
284 | cisdump_t *cis; | ||
285 | ssize_t ret = count; | ||
286 | |||
287 | if (off) | ||
288 | return -EINVAL; | ||
289 | |||
290 | if (count >= 0x200) | ||
291 | return -EINVAL; | ||
292 | |||
293 | if (!(s->state & SOCKET_PRESENT)) | ||
294 | return -ENODEV; | ||
295 | |||
296 | cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL); | ||
297 | if (!cis) | ||
298 | return -ENOMEM; | ||
299 | memset(cis, 0, sizeof(cisdump_t)); | ||
300 | |||
301 | cis->Length = count + 1; | ||
302 | memcpy(cis->Data, buf, count); | ||
303 | |||
304 | if (pcmcia_replace_cis(s, cis)) | ||
305 | ret = -EIO; | ||
306 | |||
307 | kfree(cis); | ||
308 | |||
309 | if (!ret) { | ||
170 | down(&s->skt_sem); | 310 | down(&s->skt_sem); |
171 | if ((s->callback) && | 311 | if ((s->callback) && (s->state & SOCKET_PRESENT) && |
172 | (s->state & SOCKET_PRESENT) && | ||
173 | !(s->state & SOCKET_CARDBUS)) { | 312 | !(s->state & SOCKET_CARDBUS)) { |
174 | if (try_module_get(s->callback->owner)) { | 313 | if (try_module_get(s->callback->owner)) { |
175 | s->callback->resources_done(s); | 314 | s->callback->requery(s); |
176 | module_put(s->callback->owner); | 315 | module_put(s->callback->owner); |
177 | } | 316 | } |
178 | } | 317 | } |
179 | up(&s->skt_sem); | 318 | up(&s->skt_sem); |
180 | |||
181 | return count; | ||
182 | } | 319 | } |
183 | spin_unlock_irqrestore(&s->lock, flags); | ||
184 | 320 | ||
185 | return count; | 321 | |
322 | return (ret); | ||
186 | } | 323 | } |
187 | static CLASS_DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); | ||
188 | 324 | ||
189 | 325 | ||
190 | static struct class_device_attribute *pccard_socket_attributes[] = { | 326 | static struct class_device_attribute *pccard_socket_attributes[] = { |
@@ -199,6 +335,13 @@ static struct class_device_attribute *pccard_socket_attributes[] = { | |||
199 | NULL, | 335 | NULL, |
200 | }; | 336 | }; |
201 | 337 | ||
338 | static struct bin_attribute pccard_cis_attr = { | ||
339 | .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE}, | ||
340 | .size = 0x200, | ||
341 | .read = pccard_show_cis, | ||
342 | .write = pccard_store_cis, | ||
343 | }; | ||
344 | |||
202 | static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) | 345 | static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) |
203 | { | 346 | { |
204 | struct class_device_attribute **attr; | 347 | struct class_device_attribute **attr; |
@@ -209,6 +352,8 @@ static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) | |||
209 | if (ret) | 352 | if (ret) |
210 | break; | 353 | break; |
211 | } | 354 | } |
355 | if (!ret) | ||
356 | ret = sysfs_create_bin_file(&class_dev->kobj, &pccard_cis_attr); | ||
212 | 357 | ||
213 | return ret; | 358 | return ret; |
214 | } | 359 | } |
@@ -217,6 +362,7 @@ static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev) | |||
217 | { | 362 | { |
218 | struct class_device_attribute **attr; | 363 | struct class_device_attribute **attr; |
219 | 364 | ||
365 | sysfs_remove_bin_file(&class_dev->kobj, &pccard_cis_attr); | ||
220 | for (attr = pccard_socket_attributes; *attr; attr++) | 366 | for (attr = pccard_socket_attributes; *attr; attr++) |
221 | class_device_remove_file(class_dev, *attr); | 367 | class_device_remove_file(class_dev, *attr); |
222 | } | 368 | } |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index bee05362fd24..02b23abc2df1 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -549,6 +549,11 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ | |||
549 | unsigned offset; | 549 | unsigned offset; |
550 | unsigned mask; | 550 | unsigned mask; |
551 | 551 | ||
552 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; | ||
553 | /* Already allocated? */ | ||
554 | if (res->parent) | ||
555 | return 0; | ||
556 | |||
552 | /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ | 557 | /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ |
553 | mask = ~0xfff; | 558 | mask = ~0xfff; |
554 | if (type & IORESOURCE_IO) | 559 | if (type & IORESOURCE_IO) |
@@ -556,7 +561,6 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ | |||
556 | 561 | ||
557 | offset = 0x1c + 8*nr; | 562 | offset = 0x1c + 8*nr; |
558 | bus = socket->dev->subordinate; | 563 | bus = socket->dev->subordinate; |
559 | res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; | ||
560 | res->name = bus->name; | 564 | res->name = bus->name; |
561 | res->flags = type; | 565 | res->flags = type; |
562 | res->start = 0; | 566 | res->start = 0; |
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index e60b4c0a8427..f1f6bf596dc9 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c | |||
@@ -318,6 +318,16 @@ static int aha152x_event(event_t event, int priority, | |||
318 | return 0; | 318 | return 0; |
319 | } | 319 | } |
320 | 320 | ||
321 | static struct pcmcia_device_id aha152x_ids[] = { | ||
322 | PCMCIA_DEVICE_PROD_ID123("New Media", "SCSI", "Bus Toaster", 0xcdf7e4cc, 0x35f26476, 0xa8851d6e), | ||
323 | PCMCIA_DEVICE_PROD_ID123("NOTEWORTHY", "SCSI", "Bus Toaster", 0xad89c6e8, 0x35f26476, 0xa8851d6e), | ||
324 | PCMCIA_DEVICE_PROD_ID12("Adaptec, Inc.", "APA-1460 SCSI Host Adapter", 0x24ba9738, 0x3a3c3d20), | ||
325 | PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Multimedia Sound/SCSI", 0x085a850b, 0x80a6535c), | ||
326 | PCMCIA_DEVICE_PROD_ID12("NOTEWORTHY", "NWCOMB02 SCSI/AUDIO COMBO CARD", 0xad89c6e8, 0x5f9a615b), | ||
327 | PCMCIA_DEVICE_NULL, | ||
328 | }; | ||
329 | MODULE_DEVICE_TABLE(pcmcia, aha152x_ids); | ||
330 | |||
321 | static struct pcmcia_driver aha152x_cs_driver = { | 331 | static struct pcmcia_driver aha152x_cs_driver = { |
322 | .owner = THIS_MODULE, | 332 | .owner = THIS_MODULE, |
323 | .drv = { | 333 | .drv = { |
@@ -325,6 +335,7 @@ static struct pcmcia_driver aha152x_cs_driver = { | |||
325 | }, | 335 | }, |
326 | .attach = aha152x_attach, | 336 | .attach = aha152x_attach, |
327 | .detach = aha152x_detach, | 337 | .detach = aha152x_detach, |
338 | .id_table = aha152x_ids, | ||
328 | }; | 339 | }; |
329 | 340 | ||
330 | static int __init init_aha152x_cs(void) | 341 | static int __init init_aha152x_cs(void) |
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 3df7bc72e354..853e6ee9b71a 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c | |||
@@ -299,6 +299,15 @@ static int fdomain_event(event_t event, int priority, | |||
299 | return 0; | 299 | return 0; |
300 | } /* fdomain_event */ | 300 | } /* fdomain_event */ |
301 | 301 | ||
302 | |||
303 | static struct pcmcia_device_id fdomain_ids[] = { | ||
304 | PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20), | ||
305 | PCMCIA_DEVICE_PROD_ID1("SCSI PCMCIA Adapter Card", 0x8dacb57e), | ||
306 | PCMCIA_DEVICE_PROD_ID12(" SIMPLE TECHNOLOGY Corporation", "SCSI PCMCIA Credit Card Controller", 0x182bdafe, 0xc80d106f), | ||
307 | PCMCIA_DEVICE_NULL, | ||
308 | }; | ||
309 | MODULE_DEVICE_TABLE(pcmcia, fdomain_ids); | ||
310 | |||
302 | static struct pcmcia_driver fdomain_cs_driver = { | 311 | static struct pcmcia_driver fdomain_cs_driver = { |
303 | .owner = THIS_MODULE, | 312 | .owner = THIS_MODULE, |
304 | .drv = { | 313 | .drv = { |
@@ -306,6 +315,7 @@ static struct pcmcia_driver fdomain_cs_driver = { | |||
306 | }, | 315 | }, |
307 | .attach = fdomain_attach, | 316 | .attach = fdomain_attach, |
308 | .detach = fdomain_detach, | 317 | .detach = fdomain_detach, |
318 | .id_table = fdomain_ids, | ||
309 | }; | 319 | }; |
310 | 320 | ||
311 | static int __init init_fdomain_cs(void) | 321 | static int __init init_fdomain_cs(void) |
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 3dddb323e718..91b3f28e7a19 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c | |||
@@ -2125,6 +2125,18 @@ static int nsp_cs_event(event_t event, | |||
2125 | * module entry point | 2125 | * module entry point |
2126 | *====================================================================*/ | 2126 | *====================================================================*/ |
2127 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) | 2127 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) |
2128 | static struct pcmcia_device_id nsp_cs_ids[] = { | ||
2129 | PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16 ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a), | ||
2130 | PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a), | ||
2131 | PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-002", "1", 0x534c02bc, 0xcb09d5b2, 0x51de003a), | ||
2132 | PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-003", "1", 0x534c02bc, 0xbc0ee524, 0x51de003a), | ||
2133 | PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-004", "1", 0x534c02bc, 0x226a7087, 0x51de003a), | ||
2134 | PCMCIA_DEVICE_PROD_ID123("WBT", "NinjaSCSI-3", "R1.0", 0xc7ba805f, 0xfdc7c97d, 0x6973710e), | ||
2135 | PCMCIA_DEVICE_PROD_ID123("WORKBIT", "UltraNinja-16", "1", 0x28191418, 0xb70f4b09, 0x51de003a), | ||
2136 | PCMCIA_DEVICE_NULL | ||
2137 | }; | ||
2138 | MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids); | ||
2139 | |||
2128 | static struct pcmcia_driver nsp_driver = { | 2140 | static struct pcmcia_driver nsp_driver = { |
2129 | .owner = THIS_MODULE, | 2141 | .owner = THIS_MODULE, |
2130 | .drv = { | 2142 | .drv = { |
@@ -2132,6 +2144,7 @@ static struct pcmcia_driver nsp_driver = { | |||
2132 | }, | 2144 | }, |
2133 | .attach = nsp_cs_attach, | 2145 | .attach = nsp_cs_attach, |
2134 | .detach = nsp_cs_detach, | 2146 | .detach = nsp_cs_detach, |
2147 | .id_table = nsp_cs_ids, | ||
2135 | }; | 2148 | }; |
2136 | #endif | 2149 | #endif |
2137 | 2150 | ||
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index a0175f5d11cd..0dcf41102abf 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c | |||
@@ -395,6 +395,27 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg | |||
395 | return 0; | 395 | return 0; |
396 | } /* qlogic_event */ | 396 | } /* qlogic_event */ |
397 | 397 | ||
398 | static struct pcmcia_device_id qlogic_ids[] = { | ||
399 | PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6), | ||
400 | PCMCIA_DEVICE_PROD_ID12("EPSON", "SCSI-2 PC Card SC200", 0xd361772f, 0x299d1751), | ||
401 | PCMCIA_DEVICE_PROD_ID12("MACNICA", "MIRACLE SCSI-II mPS110", 0x20841b68, 0xab3c3b6d), | ||
402 | PCMCIA_DEVICE_PROD_ID12("MIDORI ELECTRONICS ", "CN-SC43", 0x6534382a, 0xd67eee79), | ||
403 | PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J03R", 0x18df0ba0, 0x24662e8a), | ||
404 | PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC003", 0x82375a27, 0xf68e5bf7), | ||
405 | PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC004", 0x82375a27, 0x68eace54), | ||
406 | PCMCIA_DEVICE_PROD_ID12("KME", "KXLC101", 0x3faee676, 0x194250ec), | ||
407 | PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05", 0xd77b2930, 0xa85b2735), | ||
408 | PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05 rev 1.10", 0xd77b2930, 0x70f8b5f8), | ||
409 | PCMCIA_DEVICE_PROD_ID123("KME", "KXLC002", "00", 0x3faee676, 0x81896b61, 0xf99f065f), | ||
410 | PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "SCSI2 CARD 37", 0x85c10e17, 0x1a2640c1), | ||
411 | PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200A PC CARD SCSI", 0xb4585a1a, 0xa6f06ebe), | ||
412 | PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200B PC CARD SCSI-10", 0xb4585a1a, 0x0a88dea0), | ||
413 | /* these conflict with other cards! */ | ||
414 | /* PCMCIA_DEVICE_PROD_ID123("MACNICA", "MIRACLE SCSI", "mPS100", 0x20841b68, 0xf8dedaeb, 0x89f7fafb), */ | ||
415 | /* PCMCIA_DEVICE_PROD_ID123("MACNICA", "MIRACLE SCSI", "mPS100", 0x20841b68, 0xf8dedaeb, 0x89f7fafb), */ | ||
416 | PCMCIA_DEVICE_NULL, | ||
417 | }; | ||
418 | MODULE_DEVICE_TABLE(pcmcia, qlogic_ids); | ||
398 | 419 | ||
399 | static struct pcmcia_driver qlogic_cs_driver = { | 420 | static struct pcmcia_driver qlogic_cs_driver = { |
400 | .owner = THIS_MODULE, | 421 | .owner = THIS_MODULE, |
@@ -403,6 +424,7 @@ static struct pcmcia_driver qlogic_cs_driver = { | |||
403 | }, | 424 | }, |
404 | .attach = qlogic_attach, | 425 | .attach = qlogic_attach, |
405 | .detach = qlogic_detach, | 426 | .detach = qlogic_detach, |
427 | .id_table = qlogic_ids, | ||
406 | }; | 428 | }; |
407 | 429 | ||
408 | static int __init init_qlogic_cs(void) | 430 | static int __init init_qlogic_cs(void) |
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 1667da9508b4..7d4b16b6797d 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c | |||
@@ -999,6 +999,14 @@ MODULE_AUTHOR("Bob Tracy <rct@frus.com>"); | |||
999 | MODULE_DESCRIPTION("SYM53C500 PCMCIA SCSI driver"); | 999 | MODULE_DESCRIPTION("SYM53C500 PCMCIA SCSI driver"); |
1000 | MODULE_LICENSE("GPL"); | 1000 | MODULE_LICENSE("GPL"); |
1001 | 1001 | ||
1002 | static struct pcmcia_device_id sym53c500_ids[] = { | ||
1003 | PCMCIA_DEVICE_PROD_ID12("BASICS by New Media Corporation", "SCSI Sym53C500", 0x23c78a9d, 0x0099e7f7), | ||
1004 | PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "SCSI Bus Toaster Sym53C500", 0x085a850b, 0x45432eb8), | ||
1005 | PCMCIA_DEVICE_PROD_ID2("SCSI9000", 0x21648f44), | ||
1006 | PCMCIA_DEVICE_NULL, | ||
1007 | }; | ||
1008 | MODULE_DEVICE_TABLE(pcmcia, sym53c500_ids); | ||
1009 | |||
1002 | static struct pcmcia_driver sym53c500_cs_driver = { | 1010 | static struct pcmcia_driver sym53c500_cs_driver = { |
1003 | .owner = THIS_MODULE, | 1011 | .owner = THIS_MODULE, |
1004 | .drv = { | 1012 | .drv = { |
@@ -1006,6 +1014,7 @@ static struct pcmcia_driver sym53c500_cs_driver = { | |||
1006 | }, | 1014 | }, |
1007 | .attach = SYM53C500_attach, | 1015 | .attach = SYM53C500_attach, |
1008 | .detach = SYM53C500_detach, | 1016 | .detach = SYM53C500_detach, |
1017 | .id_table = sym53c500_ids, | ||
1009 | }; | 1018 | }; |
1010 | 1019 | ||
1011 | static int __init | 1020 | static int __init |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 0d7b65f93e8d..73a34b18866f 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -772,6 +772,111 @@ serial_event(event_t event, int priority, event_callback_args_t * args) | |||
772 | return 0; | 772 | return 0; |
773 | } | 773 | } |
774 | 774 | ||
775 | static struct pcmcia_device_id serial_ids[] = { | ||
776 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021), | ||
777 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a), | ||
778 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a), | ||
779 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15), | ||
780 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501), | ||
781 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a), | ||
782 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a), | ||
783 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341), | ||
784 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab), | ||
785 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081), | ||
786 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101), | ||
787 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab), | ||
788 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a), | ||
789 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a), | ||
790 | PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), | ||
791 | PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63), | ||
792 | PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef), | ||
793 | PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef), | ||
794 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), | ||
795 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), | ||
796 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), | ||
797 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), | ||
798 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), | ||
799 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet ", 0x578ba6e7, 0x02d92d1e), | ||
800 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), | ||
801 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), | ||
802 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), | ||
803 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), | ||
804 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), | ||
805 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), | ||
806 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), | ||
807 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), | ||
808 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), | ||
809 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), | ||
810 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), | ||
811 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet", 0x2e3ee845, 0xc0e778c2), | ||
812 | PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070), | ||
813 | PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562), | ||
814 | PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070), | ||
815 | PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020), | ||
816 | PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f), | ||
817 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c), | ||
818 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3), | ||
819 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15), | ||
820 | PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77), | ||
821 | PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302), | ||
822 | PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301), | ||
823 | PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039), | ||
824 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006), | ||
825 | PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a), | ||
826 | PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50), | ||
827 | PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51), | ||
828 | PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52), | ||
829 | PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53), | ||
830 | PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180), | ||
831 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e), | ||
832 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b), | ||
833 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025), | ||
834 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045), | ||
835 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052), | ||
836 | PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae), | ||
837 | PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef), | ||
838 | PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef), | ||
839 | PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef), | ||
840 | PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0), | ||
841 | PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a), | ||
842 | PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02), | ||
843 | PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa), | ||
844 | PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76), | ||
845 | PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95), | ||
846 | PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed), | ||
847 | PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65), | ||
848 | PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6), | ||
849 | PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400", 0x816cc815, 0x23539b80), | ||
850 | PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f), | ||
851 | PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f), | ||
852 | PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383), | ||
853 | PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e), | ||
854 | PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a), | ||
855 | PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab), | ||
856 | PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f), | ||
857 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), | ||
858 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), | ||
859 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), | ||
860 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"), | ||
861 | PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), | ||
862 | PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), | ||
863 | PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), | ||
864 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"), | ||
865 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), | ||
866 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), | ||
867 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), | ||
868 | PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), | ||
869 | PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), | ||
870 | PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), | ||
871 | PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), | ||
872 | /* too generic */ | ||
873 | /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ | ||
874 | /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ | ||
875 | PCMCIA_DEVICE_FUNC_ID(2), | ||
876 | PCMCIA_DEVICE_NULL, | ||
877 | }; | ||
878 | MODULE_DEVICE_TABLE(pcmcia, serial_ids); | ||
879 | |||
775 | static struct pcmcia_driver serial_cs_driver = { | 880 | static struct pcmcia_driver serial_cs_driver = { |
776 | .owner = THIS_MODULE, | 881 | .owner = THIS_MODULE, |
777 | .drv = { | 882 | .drv = { |
@@ -779,6 +884,7 @@ static struct pcmcia_driver serial_cs_driver = { | |||
779 | }, | 884 | }, |
780 | .attach = serial_attach, | 885 | .attach = serial_attach, |
781 | .detach = serial_detach, | 886 | .detach = serial_detach, |
887 | .id_table = serial_ids, | ||
782 | }; | 888 | }; |
783 | 889 | ||
784 | static int __init init_serial_cs(void) | 890 | static int __init init_serial_cs(void) |
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index e1ef0d7ee8d1..ce5ebfe4af2b 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c | |||
@@ -295,6 +295,12 @@ static int ixj_event(event_t event, int priority, event_callback_args_t * args) | |||
295 | return 0; | 295 | return 0; |
296 | } | 296 | } |
297 | 297 | ||
298 | static struct pcmcia_device_id ixj_ids[] = { | ||
299 | PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600), | ||
300 | PCMCIA_DEVICE_NULL | ||
301 | }; | ||
302 | MODULE_DEVICE_TABLE(pcmcia, ixj_ids); | ||
303 | |||
298 | static struct pcmcia_driver ixj_driver = { | 304 | static struct pcmcia_driver ixj_driver = { |
299 | .owner = THIS_MODULE, | 305 | .owner = THIS_MODULE, |
300 | .drv = { | 306 | .drv = { |
@@ -302,6 +308,7 @@ static struct pcmcia_driver ixj_driver = { | |||
302 | }, | 308 | }, |
303 | .attach = ixj_attach, | 309 | .attach = ixj_attach, |
304 | .detach = ixj_detach, | 310 | .detach = ixj_detach, |
311 | .id_table = ixj_ids, | ||
305 | }; | 312 | }; |
306 | 313 | ||
307 | static int __init ixj_pcmcia_init(void) | 314 | static int __init ixj_pcmcia_init(void) |
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 6e173265095c..269d8ef01459 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c | |||
@@ -68,13 +68,6 @@ static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; | |||
68 | 68 | ||
69 | static dev_link_t *dev_list = NULL; | 69 | static dev_link_t *dev_list = NULL; |
70 | 70 | ||
71 | static int irq_list[4] = { -1 }; | ||
72 | static int irq_list_count; | ||
73 | |||
74 | module_param_array(irq_list, int, &irq_list_count, 0444); | ||
75 | |||
76 | INT_MODULE_PARM(irq_mask, 0xdeb8); | ||
77 | |||
78 | typedef struct local_info_t { | 71 | typedef struct local_info_t { |
79 | dev_link_t link; | 72 | dev_link_t link; |
80 | dev_node_t node; | 73 | dev_node_t node; |
@@ -373,7 +366,7 @@ static dev_link_t *sl811_cs_attach(void) | |||
373 | local_info_t *local; | 366 | local_info_t *local; |
374 | dev_link_t *link; | 367 | dev_link_t *link; |
375 | client_reg_t client_reg; | 368 | client_reg_t client_reg; |
376 | int ret, i; | 369 | int ret; |
377 | 370 | ||
378 | local = kmalloc(sizeof(local_info_t), GFP_KERNEL); | 371 | local = kmalloc(sizeof(local_info_t), GFP_KERNEL); |
379 | if (!local) | 372 | if (!local) |
@@ -385,11 +378,6 @@ static dev_link_t *sl811_cs_attach(void) | |||
385 | /* Initialize */ | 378 | /* Initialize */ |
386 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 379 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
387 | link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; | 380 | link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; |
388 | if (irq_list[0] == -1) | ||
389 | link->irq.IRQInfo2 = irq_mask; | ||
390 | else | ||
391 | for (i = 0; i < irq_list_count; i++) | ||
392 | link->irq.IRQInfo2 |= 1 << irq_list[i]; | ||
393 | link->irq.Handler = NULL; | 381 | link->irq.Handler = NULL; |
394 | 382 | ||
395 | link->conf.Attributes = 0; | 383 | link->conf.Attributes = 0; |
@@ -418,6 +406,12 @@ static dev_link_t *sl811_cs_attach(void) | |||
418 | return link; | 406 | return link; |
419 | } | 407 | } |
420 | 408 | ||
409 | static struct pcmcia_device_id sl811_ids[] = { | ||
410 | PCMCIA_DEVICE_MANF_CARD(0xc015, 0x0001), /* RATOC USB HOST CF+ Card */ | ||
411 | PCMCIA_DEVICE_NULL, | ||
412 | }; | ||
413 | MODULE_DEVICE_TABLE(pcmcia, sl811_ids); | ||
414 | |||
421 | static struct pcmcia_driver sl811_cs_driver = { | 415 | static struct pcmcia_driver sl811_cs_driver = { |
422 | .owner = THIS_MODULE, | 416 | .owner = THIS_MODULE, |
423 | .drv = { | 417 | .drv = { |
@@ -425,6 +419,7 @@ static struct pcmcia_driver sl811_cs_driver = { | |||
425 | }, | 419 | }, |
426 | .attach = sl811_cs_attach, | 420 | .attach = sl811_cs_attach, |
427 | .detach = sl811_cs_detach, | 421 | .detach = sl811_cs_detach, |
422 | .id_table = sl811_ids, | ||
428 | }; | 423 | }; |
429 | 424 | ||
430 | /*====================================================================*/ | 425 | /*====================================================================*/ |
diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h index 859ebf4da632..79dfab87135d 100644 --- a/include/asm-i386/ide.h +++ b/include/asm-i386/ide.h | |||
@@ -41,13 +41,17 @@ static __inline__ int ide_default_irq(unsigned long base) | |||
41 | 41 | ||
42 | static __inline__ unsigned long ide_default_io_base(int index) | 42 | static __inline__ unsigned long ide_default_io_base(int index) |
43 | { | 43 | { |
44 | if (pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) == NULL) { | ||
45 | switch(index) { | ||
46 | case 2: return 0x1e8; | ||
47 | case 3: return 0x168; | ||
48 | case 4: return 0x1e0; | ||
49 | case 5: return 0x160; | ||
50 | } | ||
51 | } | ||
44 | switch (index) { | 52 | switch (index) { |
45 | case 0: return 0x1f0; | 53 | case 0: return 0x1f0; |
46 | case 1: return 0x170; | 54 | case 1: return 0x170; |
47 | case 2: return 0x1e8; | ||
48 | case 3: return 0x168; | ||
49 | case 4: return 0x1e0; | ||
50 | case 5: return 0x160; | ||
51 | default: | 55 | default: |
52 | return 0; | 56 | return 0; |
53 | } | 57 | } |
diff --git a/include/asm-sparc64/auxio.h b/include/asm-sparc64/auxio.h index 5eb01dd47150..81a590a50a1f 100644 --- a/include/asm-sparc64/auxio.h +++ b/include/asm-sparc64/auxio.h | |||
@@ -75,6 +75,8 @@ | |||
75 | 75 | ||
76 | #ifndef __ASSEMBLY__ | 76 | #ifndef __ASSEMBLY__ |
77 | 77 | ||
78 | extern void __iomem *auxio_register; | ||
79 | |||
78 | #define AUXIO_LTE_ON 1 | 80 | #define AUXIO_LTE_ON 1 |
79 | #define AUXIO_LTE_OFF 0 | 81 | #define AUXIO_LTE_OFF 0 |
80 | 82 | ||
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h index e071b4b4edfd..49d49a285943 100644 --- a/include/asm-sparc64/floppy.h +++ b/include/asm-sparc64/floppy.h | |||
@@ -159,7 +159,7 @@ static void sun_82077_fd_outb(unsigned char value, unsigned long port) | |||
159 | * underruns. If non-zero, doing_pdma encodes the direction of | 159 | * underruns. If non-zero, doing_pdma encodes the direction of |
160 | * the transfer for debugging. 1=read 2=write | 160 | * the transfer for debugging. 1=read 2=write |
161 | */ | 161 | */ |
162 | char *pdma_vaddr; | 162 | unsigned char *pdma_vaddr; |
163 | unsigned long pdma_size; | 163 | unsigned long pdma_size; |
164 | volatile int doing_pdma = 0; | 164 | volatile int doing_pdma = 0; |
165 | 165 | ||
@@ -209,8 +209,7 @@ static void sun_fd_enable_dma(void) | |||
209 | pdma_areasize = pdma_size; | 209 | pdma_areasize = pdma_size; |
210 | } | 210 | } |
211 | 211 | ||
212 | /* Our low-level entry point in arch/sparc/kernel/entry.S */ | 212 | extern irqreturn_t sparc_floppy_irq(int, void *, struct pt_regs *); |
213 | extern irqreturn_t floppy_hardint(int irq, void *unused, struct pt_regs *regs); | ||
214 | 213 | ||
215 | static int sun_fd_request_irq(void) | 214 | static int sun_fd_request_irq(void) |
216 | { | 215 | { |
@@ -220,8 +219,8 @@ static int sun_fd_request_irq(void) | |||
220 | if(!once) { | 219 | if(!once) { |
221 | once = 1; | 220 | once = 1; |
222 | 221 | ||
223 | error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, | 222 | error = request_irq(FLOPPY_IRQ, sparc_floppy_irq, |
224 | SA_INTERRUPT, "floppy", NULL); | 223 | SA_INTERRUPT, "floppy", NULL); |
225 | 224 | ||
226 | return ((error == 0) ? 0 : -1); | 225 | return ((error == 0) ? 0 : -1); |
227 | } | 226 | } |
@@ -615,7 +614,7 @@ static unsigned long __init sun_floppy_init(void) | |||
615 | struct linux_ebus *ebus; | 614 | struct linux_ebus *ebus; |
616 | struct linux_ebus_device *edev = NULL; | 615 | struct linux_ebus_device *edev = NULL; |
617 | unsigned long config = 0; | 616 | unsigned long config = 0; |
618 | unsigned long auxio_reg; | 617 | void __iomem *auxio_reg; |
619 | 618 | ||
620 | for_each_ebus(ebus) { | 619 | for_each_ebus(ebus) { |
621 | for_each_ebusdev(edev, ebus) { | 620 | for_each_ebusdev(edev, ebus) { |
@@ -642,7 +641,7 @@ static unsigned long __init sun_floppy_init(void) | |||
642 | /* Make sure the high density bit is set, some systems | 641 | /* Make sure the high density bit is set, some systems |
643 | * (most notably Ultra5/Ultra10) come up with it clear. | 642 | * (most notably Ultra5/Ultra10) come up with it clear. |
644 | */ | 643 | */ |
645 | auxio_reg = edev->resource[2].start; | 644 | auxio_reg = (void __iomem *) edev->resource[2].start; |
646 | writel(readl(auxio_reg)|0x2, auxio_reg); | 645 | writel(readl(auxio_reg)|0x2, auxio_reg); |
647 | 646 | ||
648 | sun_pci_ebus_dev = ebus->self; | 647 | sun_pci_ebus_dev = ebus->self; |
@@ -650,7 +649,8 @@ static unsigned long __init sun_floppy_init(void) | |||
650 | spin_lock_init(&sun_pci_fd_ebus_dma.lock); | 649 | spin_lock_init(&sun_pci_fd_ebus_dma.lock); |
651 | 650 | ||
652 | /* XXX ioremap */ | 651 | /* XXX ioremap */ |
653 | sun_pci_fd_ebus_dma.regs = edev->resource[1].start; | 652 | sun_pci_fd_ebus_dma.regs = (void __iomem *) |
653 | edev->resource[1].start; | ||
654 | if (!sun_pci_fd_ebus_dma.regs) | 654 | if (!sun_pci_fd_ebus_dma.regs) |
655 | return 0; | 655 | return 0; |
656 | 656 | ||
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index 3aef0ca67750..018e2e46082b 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h | |||
@@ -19,7 +19,7 @@ | |||
19 | /* You should not mess with this directly. That's the job of irq.c. | 19 | /* You should not mess with this directly. That's the job of irq.c. |
20 | * | 20 | * |
21 | * If you make changes here, please update hand coded assembler of | 21 | * If you make changes here, please update hand coded assembler of |
22 | * SBUS/floppy interrupt handler in entry.S -DaveM | 22 | * the vectored interrupt trap handler in entry.S -DaveM |
23 | * | 23 | * |
24 | * This is currently one DCACHE line, two buckets per L2 cache | 24 | * This is currently one DCACHE line, two buckets per L2 cache |
25 | * line. Keep this in mind please. | 25 | * line. Keep this in mind please. |
@@ -122,11 +122,6 @@ extern void enable_irq(unsigned int); | |||
122 | extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap); | 122 | extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap); |
123 | extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); | 123 | extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); |
124 | 124 | ||
125 | extern int request_fast_irq(unsigned int irq, | ||
126 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
127 | unsigned long flags, __const__ char *devname, | ||
128 | void *dev_id); | ||
129 | |||
130 | static __inline__ void set_softint(unsigned long bits) | 125 | static __inline__ void set_softint(unsigned long bits) |
131 | { | 126 | { |
132 | __asm__ __volatile__("wr %0, 0x0, %%set_softint" | 127 | __asm__ __volatile__("wr %0, 0x0, %%set_softint" |
diff --git a/include/asm-sparc64/rwsem.h b/include/asm-sparc64/rwsem.h index bf2ae90ed3df..a1cc94f95984 100644 --- a/include/asm-sparc64/rwsem.h +++ b/include/asm-sparc64/rwsem.h | |||
@@ -55,8 +55,9 @@ static __inline__ int rwsem_atomic_update(int delta, struct rw_semaphore *sem) | |||
55 | "add %%g1, %1, %%g7\n\t" | 55 | "add %%g1, %1, %%g7\n\t" |
56 | "cas [%2], %%g1, %%g7\n\t" | 56 | "cas [%2], %%g1, %%g7\n\t" |
57 | "cmp %%g1, %%g7\n\t" | 57 | "cmp %%g1, %%g7\n\t" |
58 | "membar #StoreLoad | #StoreStore\n\t" | ||
58 | "bne,pn %%icc, 1b\n\t" | 59 | "bne,pn %%icc, 1b\n\t" |
59 | " membar #StoreLoad | #StoreStore\n\t" | 60 | " nop\n\t" |
60 | "mov %%g7, %0\n\t" | 61 | "mov %%g7, %0\n\t" |
61 | : "=&r" (tmp) | 62 | : "=&r" (tmp) |
62 | : "0" (tmp), "r" (sem) | 63 | : "0" (tmp), "r" (sem) |
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h index db7581bdb531..9cb93a5c2b4f 100644 --- a/include/asm-sparc64/spinlock.h +++ b/include/asm-sparc64/spinlock.h | |||
@@ -52,12 +52,14 @@ static inline void _raw_spin_lock(spinlock_t *lock) | |||
52 | 52 | ||
53 | __asm__ __volatile__( | 53 | __asm__ __volatile__( |
54 | "1: ldstub [%1], %0\n" | 54 | "1: ldstub [%1], %0\n" |
55 | " membar #StoreLoad | #StoreStore\n" | ||
55 | " brnz,pn %0, 2f\n" | 56 | " brnz,pn %0, 2f\n" |
56 | " membar #StoreLoad | #StoreStore\n" | 57 | " nop\n" |
57 | " .subsection 2\n" | 58 | " .subsection 2\n" |
58 | "2: ldub [%1], %0\n" | 59 | "2: ldub [%1], %0\n" |
60 | " membar #LoadLoad\n" | ||
59 | " brnz,pt %0, 2b\n" | 61 | " brnz,pt %0, 2b\n" |
60 | " membar #LoadLoad\n" | 62 | " nop\n" |
61 | " ba,a,pt %%xcc, 1b\n" | 63 | " ba,a,pt %%xcc, 1b\n" |
62 | " .previous" | 64 | " .previous" |
63 | : "=&r" (tmp) | 65 | : "=&r" (tmp) |
@@ -95,16 +97,18 @@ static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags) | |||
95 | 97 | ||
96 | __asm__ __volatile__( | 98 | __asm__ __volatile__( |
97 | "1: ldstub [%2], %0\n" | 99 | "1: ldstub [%2], %0\n" |
98 | " brnz,pn %0, 2f\n" | ||
99 | " membar #StoreLoad | #StoreStore\n" | 100 | " membar #StoreLoad | #StoreStore\n" |
101 | " brnz,pn %0, 2f\n" | ||
102 | " nop\n" | ||
100 | " .subsection 2\n" | 103 | " .subsection 2\n" |
101 | "2: rdpr %%pil, %1\n" | 104 | "2: rdpr %%pil, %1\n" |
102 | " wrpr %3, %%pil\n" | 105 | " wrpr %3, %%pil\n" |
103 | "3: ldub [%2], %0\n" | 106 | "3: ldub [%2], %0\n" |
104 | " brnz,pt %0, 3b\n" | ||
105 | " membar #LoadLoad\n" | 107 | " membar #LoadLoad\n" |
108 | " brnz,pt %0, 3b\n" | ||
109 | " nop\n" | ||
106 | " ba,pt %%xcc, 1b\n" | 110 | " ba,pt %%xcc, 1b\n" |
107 | " wrpr %1, %%pil\n" | 111 | " wrpr %1, %%pil\n" |
108 | " .previous" | 112 | " .previous" |
109 | : "=&r" (tmp1), "=&r" (tmp2) | 113 | : "=&r" (tmp1), "=&r" (tmp2) |
110 | : "r"(lock), "r"(flags) | 114 | : "r"(lock), "r"(flags) |
@@ -162,12 +166,14 @@ static void inline __read_lock(rwlock_t *lock) | |||
162 | "4: add %0, 1, %1\n" | 166 | "4: add %0, 1, %1\n" |
163 | " cas [%2], %0, %1\n" | 167 | " cas [%2], %0, %1\n" |
164 | " cmp %0, %1\n" | 168 | " cmp %0, %1\n" |
169 | " membar #StoreLoad | #StoreStore\n" | ||
165 | " bne,pn %%icc, 1b\n" | 170 | " bne,pn %%icc, 1b\n" |
166 | " membar #StoreLoad | #StoreStore\n" | 171 | " nop\n" |
167 | " .subsection 2\n" | 172 | " .subsection 2\n" |
168 | "2: ldsw [%2], %0\n" | 173 | "2: ldsw [%2], %0\n" |
174 | " membar #LoadLoad\n" | ||
169 | " brlz,pt %0, 2b\n" | 175 | " brlz,pt %0, 2b\n" |
170 | " membar #LoadLoad\n" | 176 | " nop\n" |
171 | " ba,a,pt %%xcc, 4b\n" | 177 | " ba,a,pt %%xcc, 4b\n" |
172 | " .previous" | 178 | " .previous" |
173 | : "=&r" (tmp1), "=&r" (tmp2) | 179 | : "=&r" (tmp1), "=&r" (tmp2) |
@@ -204,12 +210,14 @@ static void inline __write_lock(rwlock_t *lock) | |||
204 | "4: or %0, %3, %1\n" | 210 | "4: or %0, %3, %1\n" |
205 | " cas [%2], %0, %1\n" | 211 | " cas [%2], %0, %1\n" |
206 | " cmp %0, %1\n" | 212 | " cmp %0, %1\n" |
213 | " membar #StoreLoad | #StoreStore\n" | ||
207 | " bne,pn %%icc, 1b\n" | 214 | " bne,pn %%icc, 1b\n" |
208 | " membar #StoreLoad | #StoreStore\n" | 215 | " nop\n" |
209 | " .subsection 2\n" | 216 | " .subsection 2\n" |
210 | "2: lduw [%2], %0\n" | 217 | "2: lduw [%2], %0\n" |
218 | " membar #LoadLoad\n" | ||
211 | " brnz,pt %0, 2b\n" | 219 | " brnz,pt %0, 2b\n" |
212 | " membar #LoadLoad\n" | 220 | " nop\n" |
213 | " ba,a,pt %%xcc, 4b\n" | 221 | " ba,a,pt %%xcc, 4b\n" |
214 | " .previous" | 222 | " .previous" |
215 | : "=&r" (tmp1), "=&r" (tmp2) | 223 | : "=&r" (tmp1), "=&r" (tmp2) |
@@ -240,8 +248,9 @@ static int inline __write_trylock(rwlock_t *lock) | |||
240 | " or %0, %4, %1\n" | 248 | " or %0, %4, %1\n" |
241 | " cas [%3], %0, %1\n" | 249 | " cas [%3], %0, %1\n" |
242 | " cmp %0, %1\n" | 250 | " cmp %0, %1\n" |
251 | " membar #StoreLoad | #StoreStore\n" | ||
243 | " bne,pn %%icc, 1b\n" | 252 | " bne,pn %%icc, 1b\n" |
244 | " membar #StoreLoad | #StoreStore\n" | 253 | " nop\n" |
245 | " mov 1, %2\n" | 254 | " mov 1, %2\n" |
246 | "2:" | 255 | "2:" |
247 | : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result) | 256 | : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result) |
diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h index 9d7613eea812..1aa932773af8 100644 --- a/include/asm-sparc64/spitfire.h +++ b/include/asm-sparc64/spitfire.h | |||
@@ -111,7 +111,6 @@ static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long | |||
111 | "membar #Sync" | 111 | "membar #Sync" |
112 | : /* No outputs */ | 112 | : /* No outputs */ |
113 | : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG)); | 113 | : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG)); |
114 | __asm__ __volatile__ ("membar #Sync" : : : "memory"); | ||
115 | } | 114 | } |
116 | 115 | ||
117 | /* The instruction cache lines are flushed with this, but note that | 116 | /* The instruction cache lines are flushed with this, but note that |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index d6eb7b2efc04..9b6d05172ed4 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -175,4 +175,50 @@ struct serio_device_id { | |||
175 | }; | 175 | }; |
176 | 176 | ||
177 | 177 | ||
178 | /* PCMCIA */ | ||
179 | |||
180 | struct pcmcia_device_id { | ||
181 | __u16 match_flags; | ||
182 | |||
183 | __u16 manf_id; | ||
184 | __u16 card_id; | ||
185 | |||
186 | __u8 func_id; | ||
187 | |||
188 | /* for real multi-function devices */ | ||
189 | __u8 function; | ||
190 | |||
191 | /* for pseude multi-function devices */ | ||
192 | __u8 device_no; | ||
193 | |||
194 | __u32 prod_id_hash[4]; | ||
195 | |||
196 | /* not matched against in kernelspace*/ | ||
197 | #ifdef __KERNEL__ | ||
198 | const char * prod_id[4]; | ||
199 | #else | ||
200 | kernel_ulong_t prod_id[4]; | ||
201 | #endif | ||
202 | |||
203 | /* not matched against */ | ||
204 | kernel_ulong_t driver_info; | ||
205 | #ifdef __KERNEL__ | ||
206 | char * cisfile; | ||
207 | #else | ||
208 | kernel_ulong_t cisfile; | ||
209 | #endif | ||
210 | }; | ||
211 | |||
212 | #define PCMCIA_DEV_ID_MATCH_MANF_ID 0x0001 | ||
213 | #define PCMCIA_DEV_ID_MATCH_CARD_ID 0x0002 | ||
214 | #define PCMCIA_DEV_ID_MATCH_FUNC_ID 0x0004 | ||
215 | #define PCMCIA_DEV_ID_MATCH_FUNCTION 0x0008 | ||
216 | #define PCMCIA_DEV_ID_MATCH_PROD_ID1 0x0010 | ||
217 | #define PCMCIA_DEV_ID_MATCH_PROD_ID2 0x0020 | ||
218 | #define PCMCIA_DEV_ID_MATCH_PROD_ID3 0x0040 | ||
219 | #define PCMCIA_DEV_ID_MATCH_PROD_ID4 0x0080 | ||
220 | #define PCMCIA_DEV_ID_MATCH_DEVICE_NO 0x0100 | ||
221 | #define PCMCIA_DEV_ID_MATCH_FAKE_CIS 0x0200 | ||
222 | #define PCMCIA_DEV_ID_MATCH_ANONYMOUS 0x0400 | ||
223 | |||
178 | #endif /* LINUX_MOD_DEVICETABLE_H */ | 224 | #endif /* LINUX_MOD_DEVICETABLE_H */ |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a3961e1d5183..1e0bc6a8d653 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -1815,6 +1815,8 @@ | |||
1815 | #define PCI_VENDOR_ID_ITE 0x1283 | 1815 | #define PCI_VENDOR_ID_ITE 0x1283 |
1816 | #define PCI_DEVICE_ID_ITE_IT8172G 0x8172 | 1816 | #define PCI_DEVICE_ID_ITE_IT8172G 0x8172 |
1817 | #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801 | 1817 | #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801 |
1818 | #define PCI_DEVICE_ID_ITE_8211 0x8211 | ||
1819 | #define PCI_DEVICE_ID_ITE_8212 0x8212 | ||
1818 | #define PCI_DEVICE_ID_ITE_8872 0x8872 | 1820 | #define PCI_DEVICE_ID_ITE_8872 0x8872 |
1819 | #define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886 | 1821 | #define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886 |
1820 | 1822 | ||
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h index 2000b43ece91..da19c297dd65 100644 --- a/include/pcmcia/ciscode.h +++ b/include/pcmcia/ciscode.h | |||
@@ -112,6 +112,8 @@ | |||
112 | 112 | ||
113 | #define MANFID_TDK 0x0105 | 113 | #define MANFID_TDK 0x0105 |
114 | #define PRODID_TDK_CF010 0x0900 | 114 | #define PRODID_TDK_CF010 0x0900 |
115 | #define PRODID_TDK_NP9610 0x0d0a | ||
116 | #define PRODID_TDK_MN3200 0x0e0a | ||
115 | #define PRODID_TDK_GN3410 0x4815 | 117 | #define PRODID_TDK_GN3410 0x4815 |
116 | 118 | ||
117 | #define MANFID_TOSHIBA 0x0098 | 119 | #define MANFID_TOSHIBA 0x0098 |
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 8d8643adc786..b42ddc0c1143 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h | |||
@@ -396,7 +396,6 @@ struct pcmcia_socket; | |||
396 | int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg); | 396 | int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg); |
397 | int pcmcia_deregister_client(client_handle_t handle); | 397 | int pcmcia_deregister_client(client_handle_t handle); |
398 | int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config); | 398 | int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config); |
399 | int pcmcia_get_card_services_info(servinfo_t *info); | ||
400 | int pcmcia_get_first_window(window_handle_t *win, win_req_t *req); | 399 | int pcmcia_get_first_window(window_handle_t *win, win_req_t *req); |
401 | int pcmcia_get_next_window(window_handle_t *win, win_req_t *req); | 400 | int pcmcia_get_next_window(window_handle_t *win, win_req_t *req); |
402 | int pcmcia_get_status(client_handle_t handle, cs_status_t *status); | 401 | int pcmcia_get_status(client_handle_t handle, cs_status_t *status); |
@@ -417,7 +416,6 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt); | |||
417 | int pcmcia_resume_card(struct pcmcia_socket *skt); | 416 | int pcmcia_resume_card(struct pcmcia_socket *skt); |
418 | int pcmcia_eject_card(struct pcmcia_socket *skt); | 417 | int pcmcia_eject_card(struct pcmcia_socket *skt); |
419 | int pcmcia_insert_card(struct pcmcia_socket *skt); | 418 | int pcmcia_insert_card(struct pcmcia_socket *skt); |
420 | int pcmcia_report_error(client_handle_t handle, error_info_t *err); | ||
421 | 419 | ||
422 | struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt); | 420 | struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt); |
423 | void pcmcia_put_socket(struct pcmcia_socket *skt); | 421 | void pcmcia_put_socket(struct pcmcia_socket *skt); |
diff --git a/include/pcmcia/device_id.h b/include/pcmcia/device_id.h new file mode 100644 index 000000000000..346d81ece287 --- /dev/null +++ b/include/pcmcia/device_id.h | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | * Copyright (2003-2004) Dominik Brodowski <linux@brodo.de> | ||
3 | * David Woodhouse | ||
4 | * | ||
5 | * License: GPL v2 | ||
6 | */ | ||
7 | |||
8 | #define PCMCIA_DEVICE_MANF_CARD(manf, card) { \ | ||
9 | .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
10 | PCMCIA_DEV_ID_MATCH_CARD_ID, \ | ||
11 | .manf_id = (manf), \ | ||
12 | .card_id = (card), } | ||
13 | |||
14 | #define PCMCIA_DEVICE_FUNC_ID(func) { \ | ||
15 | .match_flags = PCMCIA_DEV_ID_MATCH_FUNC_ID, \ | ||
16 | .func_id = (func), } | ||
17 | |||
18 | #define PCMCIA_DEVICE_PROD_ID1(v1, vh1) { \ | ||
19 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1, \ | ||
20 | .prod_id = { (v1), NULL, NULL, NULL }, \ | ||
21 | .prod_id_hash = { (vh1), 0, 0, 0 }, } | ||
22 | |||
23 | #define PCMCIA_DEVICE_PROD_ID2(v2, vh2) { \ | ||
24 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2, \ | ||
25 | .prod_id = { NULL, (v2), NULL, NULL }, \ | ||
26 | .prod_id_hash = { 0, (vh2), 0, 0 }, } | ||
27 | |||
28 | #define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \ | ||
29 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
30 | PCMCIA_DEV_ID_MATCH_PROD_ID2, \ | ||
31 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
32 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, } | ||
33 | |||
34 | #define PCMCIA_DEVICE_PROD_ID13(v1, v3, vh1, vh3) { \ | ||
35 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
36 | PCMCIA_DEV_ID_MATCH_PROD_ID3, \ | ||
37 | .prod_id = { (v1), NULL, (v3), NULL }, \ | ||
38 | .prod_id_hash = { (vh1), 0, (vh3), 0 }, } | ||
39 | |||
40 | #define PCMCIA_DEVICE_PROD_ID14(v1, v4, vh1, vh4) { \ | ||
41 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
42 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
43 | .prod_id = { (v1), NULL, NULL, (v4) }, \ | ||
44 | .prod_id_hash = { (vh1), 0, 0, (vh4) }, } | ||
45 | |||
46 | #define PCMCIA_DEVICE_PROD_ID123(v1, v2, v3, vh1, vh2, vh3) { \ | ||
47 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
48 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
49 | PCMCIA_DEV_ID_MATCH_PROD_ID3, \ | ||
50 | .prod_id = { (v1), (v2), (v3), NULL },\ | ||
51 | .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, } | ||
52 | |||
53 | #define PCMCIA_DEVICE_PROD_ID124(v1, v2, v4, vh1, vh2, vh4) { \ | ||
54 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
55 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
56 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
57 | .prod_id = { (v1), (v2), NULL, (v4) }, \ | ||
58 | .prod_id_hash = { (vh1), (vh2), 0, (vh4) }, } | ||
59 | |||
60 | #define PCMCIA_DEVICE_PROD_ID134(v1, v3, v4, vh1, vh3, vh4) { \ | ||
61 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
62 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
63 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
64 | .prod_id = { (v1), NULL, (v3), (v4) }, \ | ||
65 | .prod_id_hash = { (vh1), 0, (vh3), (vh4) }, } | ||
66 | |||
67 | #define PCMCIA_DEVICE_PROD_ID1234(v1, v2, v3, v4, vh1, vh2, vh3, vh4) { \ | ||
68 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
69 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
70 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
71 | PCMCIA_DEV_ID_MATCH_PROD_ID4, \ | ||
72 | .prod_id = { (v1), (v2), (v3), (v4) }, \ | ||
73 | .prod_id_hash = { (vh1), (vh2), (vh3), (vh4) }, } | ||
74 | |||
75 | |||
76 | /* multi-function devices */ | ||
77 | |||
78 | #define PCMCIA_MFC_DEVICE_MANF_CARD(mfc, manf, card) { \ | ||
79 | .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
80 | PCMCIA_DEV_ID_MATCH_CARD_ID| \ | ||
81 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
82 | .manf_id = (manf), \ | ||
83 | .card_id = (card), \ | ||
84 | .function = (mfc), } | ||
85 | |||
86 | #define PCMCIA_MFC_DEVICE_PROD_ID1(mfc, v1, vh1) { \ | ||
87 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
88 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
89 | .prod_id = { (v1), NULL, NULL, NULL }, \ | ||
90 | .prod_id_hash = { (vh1), 0, 0, 0 }, \ | ||
91 | .function = (mfc), } | ||
92 | |||
93 | #define PCMCIA_MFC_DEVICE_PROD_ID2(mfc, v2, vh2) { \ | ||
94 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
95 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
96 | .prod_id = { NULL, (v2), NULL, NULL }, \ | ||
97 | .prod_id_hash = { 0, (vh2), 0, 0 }, \ | ||
98 | .function = (mfc), } | ||
99 | |||
100 | #define PCMCIA_MFC_DEVICE_PROD_ID12(mfc, v1, v2, vh1, vh2) { \ | ||
101 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
102 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
103 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
104 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
105 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ | ||
106 | .function = (mfc), } | ||
107 | |||
108 | #define PCMCIA_MFC_DEVICE_PROD_ID13(mfc, v1, v3, vh1, vh3) { \ | ||
109 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
110 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
111 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
112 | .prod_id = { (v1), NULL, (v3), NULL }, \ | ||
113 | .prod_id_hash = { (vh1), 0, (vh3), 0 }, \ | ||
114 | .function = (mfc), } | ||
115 | |||
116 | #define PCMCIA_MFC_DEVICE_PROD_ID123(mfc, v1, v2, v3, vh1, vh2, vh3) { \ | ||
117 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
118 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
119 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
120 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
121 | .prod_id = { (v1), (v2), (v3), NULL },\ | ||
122 | .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ | ||
123 | .function = (mfc), } | ||
124 | |||
125 | /* pseudo multi-function devices */ | ||
126 | |||
127 | #define PCMCIA_PFC_DEVICE_MANF_CARD(mfc, manf, card) { \ | ||
128 | .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
129 | PCMCIA_DEV_ID_MATCH_CARD_ID| \ | ||
130 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
131 | .manf_id = (manf), \ | ||
132 | .card_id = (card), \ | ||
133 | .device_no = (mfc), } | ||
134 | |||
135 | #define PCMCIA_PFC_DEVICE_PROD_ID1(mfc, v1, vh1) { \ | ||
136 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
137 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
138 | .prod_id = { (v1), NULL, NULL, NULL }, \ | ||
139 | .prod_id_hash = { (vh1), 0, 0, 0 }, \ | ||
140 | .device_no = (mfc), } | ||
141 | |||
142 | #define PCMCIA_PFC_DEVICE_PROD_ID2(mfc, v2, vh2) { \ | ||
143 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
144 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
145 | .prod_id = { NULL, (v2), NULL, NULL }, \ | ||
146 | .prod_id_hash = { 0, (vh2), 0, 0 }, \ | ||
147 | .device_no = (mfc), } | ||
148 | |||
149 | #define PCMCIA_PFC_DEVICE_PROD_ID12(mfc, v1, v2, vh1, vh2) { \ | ||
150 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
151 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
152 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
153 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
154 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ | ||
155 | .device_no = (mfc), } | ||
156 | |||
157 | #define PCMCIA_PFC_DEVICE_PROD_ID13(mfc, v1, v3, vh1, vh3) { \ | ||
158 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
159 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
160 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
161 | .prod_id = { (v1), NULL, (v3), NULL }, \ | ||
162 | .prod_id_hash = { (vh1), 0, (vh3), 0 }, \ | ||
163 | .device_no = (mfc), } | ||
164 | |||
165 | #define PCMCIA_PFC_DEVICE_PROD_ID123(mfc, v1, v2, v3, vh1, vh2, vh3) { \ | ||
166 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
167 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
168 | PCMCIA_DEV_ID_MATCH_PROD_ID3| \ | ||
169 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
170 | .prod_id = { (v1), (v2), (v3), NULL },\ | ||
171 | .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ | ||
172 | .device_no = (mfc), } | ||
173 | |||
174 | /* cards needing a CIS override */ | ||
175 | |||
176 | #define PCMCIA_DEVICE_CIS_MANF_CARD(manf, card, _cisfile) { \ | ||
177 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
178 | PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
179 | PCMCIA_DEV_ID_MATCH_CARD_ID, \ | ||
180 | .manf_id = (manf), \ | ||
181 | .card_id = (card), \ | ||
182 | .cisfile = (_cisfile)} | ||
183 | |||
184 | #define PCMCIA_DEVICE_CIS_PROD_ID12(v1, v2, vh1, vh2, _cisfile) { \ | ||
185 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
186 | PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
187 | PCMCIA_DEV_ID_MATCH_PROD_ID2, \ | ||
188 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
189 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ | ||
190 | .cisfile = (_cisfile)} | ||
191 | |||
192 | #define PCMCIA_DEVICE_CIS_PROD_ID123(v1, v2, v3, vh1, vh2, vh3, _cisfile) { \ | ||
193 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
194 | PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
195 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
196 | PCMCIA_DEV_ID_MATCH_PROD_ID3, \ | ||
197 | .prod_id = { (v1), (v2), (v3), NULL },\ | ||
198 | .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ | ||
199 | .cisfile = (_cisfile)} | ||
200 | |||
201 | |||
202 | #define PCMCIA_DEVICE_CIS_PROD_ID2(v2, vh2, _cisfile) { \ | ||
203 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
204 | PCMCIA_DEV_ID_MATCH_PROD_ID2, \ | ||
205 | .prod_id = { NULL, (v2), NULL, NULL }, \ | ||
206 | .prod_id_hash = { 0, (vh2), 0, 0 }, \ | ||
207 | .cisfile = (_cisfile)} | ||
208 | |||
209 | #define PCMCIA_PFC_DEVICE_CIS_PROD_ID12(mfc, v1, v2, vh1, vh2, _cisfile) { \ | ||
210 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
211 | PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
212 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
213 | PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ | ||
214 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
215 | .prod_id_hash = { (vh1), (vh2), 0, 0 },\ | ||
216 | .device_no = (mfc), \ | ||
217 | .cisfile = (_cisfile)} | ||
218 | |||
219 | #define PCMCIA_MFC_DEVICE_CIS_MANF_CARD(mfc, manf, card, _cisfile) { \ | ||
220 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
221 | PCMCIA_DEV_ID_MATCH_MANF_ID| \ | ||
222 | PCMCIA_DEV_ID_MATCH_CARD_ID| \ | ||
223 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
224 | .manf_id = (manf), \ | ||
225 | .card_id = (card), \ | ||
226 | .function = (mfc), \ | ||
227 | .cisfile = (_cisfile)} | ||
228 | |||
229 | #define PCMCIA_MFC_DEVICE_CIS_PROD_ID12(mfc, v1, v2, vh1, vh2, _cisfile) { \ | ||
230 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
231 | PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | ||
232 | PCMCIA_DEV_ID_MATCH_PROD_ID2| \ | ||
233 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
234 | .prod_id = { (v1), (v2), NULL, NULL }, \ | ||
235 | .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ | ||
236 | .function = (mfc), \ | ||
237 | .cisfile = (_cisfile)} | ||
238 | |||
239 | #define PCMCIA_MFC_DEVICE_CIS_PROD_ID4(mfc, v4, vh4, _cisfile) { \ | ||
240 | .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ | ||
241 | PCMCIA_DEV_ID_MATCH_PROD_ID4| \ | ||
242 | PCMCIA_DEV_ID_MATCH_FUNCTION, \ | ||
243 | .prod_id = { NULL, NULL, NULL, (v4) }, \ | ||
244 | .prod_id_hash = { 0, 0, 0, (vh4) }, \ | ||
245 | .function = (mfc), \ | ||
246 | .cisfile = (_cisfile)} | ||
247 | |||
248 | |||
249 | #define PCMCIA_DEVICE_NULL { .match_flags = 0, } | ||
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 312fd958c901..2b52553f2d94 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h | |||
@@ -18,6 +18,8 @@ | |||
18 | 18 | ||
19 | #include <pcmcia/bulkmem.h> | 19 | #include <pcmcia/bulkmem.h> |
20 | #include <pcmcia/cs_types.h> | 20 | #include <pcmcia/cs_types.h> |
21 | #include <pcmcia/device_id.h> | ||
22 | #include <linux/mod_devicetable.h> | ||
21 | 23 | ||
22 | typedef struct tuple_parse_t { | 24 | typedef struct tuple_parse_t { |
23 | tuple_t tuple; | 25 | tuple_t tuple; |
@@ -129,12 +131,11 @@ typedef struct dev_link_t { | |||
129 | 131 | ||
130 | struct pcmcia_socket; | 132 | struct pcmcia_socket; |
131 | 133 | ||
132 | extern struct bus_type pcmcia_bus_type; | ||
133 | |||
134 | struct pcmcia_driver { | 134 | struct pcmcia_driver { |
135 | dev_link_t *(*attach)(void); | 135 | dev_link_t *(*attach)(void); |
136 | void (*detach)(dev_link_t *); | 136 | void (*detach)(dev_link_t *); |
137 | struct module *owner; | 137 | struct module *owner; |
138 | struct pcmcia_device_id *id_table; | ||
138 | struct device_driver drv; | 139 | struct device_driver drv; |
139 | }; | 140 | }; |
140 | 141 | ||
@@ -173,7 +174,9 @@ struct pcmcia_device { | |||
173 | u8 has_manf_id:1; | 174 | u8 has_manf_id:1; |
174 | u8 has_card_id:1; | 175 | u8 has_card_id:1; |
175 | u8 has_func_id:1; | 176 | u8 has_func_id:1; |
176 | u8 reserved:5; | 177 | |
178 | u8 allow_func_id_match:1; | ||
179 | u8 reserved:4; | ||
177 | 180 | ||
178 | u8 func_id; | 181 | u8 func_id; |
179 | u16 manf_id; | 182 | u16 manf_id; |
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 67b867f31fe4..0f7aacc33fe9 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h | |||
@@ -15,10 +15,12 @@ | |||
15 | #ifndef _LINUX_SS_H | 15 | #ifndef _LINUX_SS_H |
16 | #define _LINUX_SS_H | 16 | #define _LINUX_SS_H |
17 | 17 | ||
18 | #include <linux/config.h> | ||
19 | #include <linux/device.h> | ||
20 | |||
18 | #include <pcmcia/cs_types.h> | 21 | #include <pcmcia/cs_types.h> |
19 | #include <pcmcia/cs.h> | 22 | #include <pcmcia/cs.h> |
20 | #include <pcmcia/bulkmem.h> | 23 | #include <pcmcia/bulkmem.h> |
21 | #include <linux/device.h> | ||
22 | 24 | ||
23 | /* Definitions for card status flags for GetStatus */ | 25 | /* Definitions for card status flags for GetStatus */ |
24 | #define SS_WRPROT 0x0001 | 26 | #define SS_WRPROT 0x0001 |
@@ -171,7 +173,7 @@ typedef struct window_t { | |||
171 | 173 | ||
172 | struct config_t; | 174 | struct config_t; |
173 | struct pcmcia_callback; | 175 | struct pcmcia_callback; |
174 | 176 | struct user_info_t; | |
175 | 177 | ||
176 | struct pcmcia_socket { | 178 | struct pcmcia_socket { |
177 | struct module *owner; | 179 | struct module *owner; |
@@ -216,8 +218,9 @@ struct pcmcia_socket { | |||
216 | 218 | ||
217 | /* is set to one if resource setup is done using adjust_resource_info() */ | 219 | /* is set to one if resource setup is done using adjust_resource_info() */ |
218 | u8 resource_setup_old:1; | 220 | u8 resource_setup_old:1; |
221 | u8 resource_setup_new:1; | ||
219 | 222 | ||
220 | u8 reserved:6; | 223 | u8 reserved:5; |
221 | 224 | ||
222 | /* socket operations */ | 225 | /* socket operations */ |
223 | struct pccard_operations * ops; | 226 | struct pccard_operations * ops; |
@@ -241,9 +244,32 @@ struct pcmcia_socket { | |||
241 | unsigned int thread_events; | 244 | unsigned int thread_events; |
242 | 245 | ||
243 | /* pcmcia (16-bit) */ | 246 | /* pcmcia (16-bit) */ |
244 | struct pcmcia_bus_socket *pcmcia; | ||
245 | struct pcmcia_callback *callback; | 247 | struct pcmcia_callback *callback; |
246 | 248 | ||
249 | #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) | ||
250 | struct list_head devices_list; /* PCMCIA devices */ | ||
251 | u8 device_count; /* the number of devices, used | ||
252 | * only internally and subject | ||
253 | * to incorrectness and change */ | ||
254 | |||
255 | struct { | ||
256 | u8 present:1, /* PCMCIA card is present in socket */ | ||
257 | busy:1, /* "master" ioctl is used */ | ||
258 | dead:1, /* pcmcia module is being unloaded */ | ||
259 | device_add_pending:1, /* a pseudo-multifunction-device | ||
260 | * add event is pending */ | ||
261 | reserved:4; | ||
262 | } pcmcia_state; | ||
263 | |||
264 | struct work_struct device_add; /* for adding further pseudo-multifunction | ||
265 | * devices */ | ||
266 | |||
267 | #ifdef CONFIG_PCMCIA_IOCTL | ||
268 | struct user_info_t *user; | ||
269 | wait_queue_head_t queue; | ||
270 | #endif | ||
271 | #endif | ||
272 | |||
247 | /* cardbus (32-bit) */ | 273 | /* cardbus (32-bit) */ |
248 | #ifdef CONFIG_CARDBUS | 274 | #ifdef CONFIG_CARDBUS |
249 | struct resource * cb_cis_res; | 275 | struct resource * cb_cis_res; |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 32197efe67ed..908bff6d1eef 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -287,6 +287,42 @@ static int do_pnp_card_entry(const char *filename, | |||
287 | return 1; | 287 | return 1; |
288 | } | 288 | } |
289 | 289 | ||
290 | /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */ | ||
291 | static int do_pcmcia_entry(const char *filename, | ||
292 | struct pcmcia_device_id *id, char *alias) | ||
293 | { | ||
294 | unsigned int i; | ||
295 | |||
296 | id->manf_id = TO_NATIVE(id->manf_id); | ||
297 | id->card_id = TO_NATIVE(id->card_id); | ||
298 | id->func_id = TO_NATIVE(id->func_id); | ||
299 | id->function = TO_NATIVE(id->function); | ||
300 | id->device_no = TO_NATIVE(id->device_no); | ||
301 | for (i=0; i<4; i++) { | ||
302 | id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]); | ||
303 | } | ||
304 | |||
305 | strcpy(alias, "pcmcia:"); | ||
306 | ADD(alias, "m", id->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID, | ||
307 | id->manf_id); | ||
308 | ADD(alias, "c", id->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID, | ||
309 | id->card_id); | ||
310 | ADD(alias, "f", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID, | ||
311 | id->func_id); | ||
312 | ADD(alias, "fn", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION, | ||
313 | id->function); | ||
314 | ADD(alias, "pfn", id->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO, | ||
315 | id->device_no); | ||
316 | ADD(alias, "pa", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, id->prod_id_hash[0]); | ||
317 | ADD(alias, "pb", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, id->prod_id_hash[1]); | ||
318 | ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]); | ||
319 | ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]); | ||
320 | |||
321 | return 1; | ||
322 | } | ||
323 | |||
324 | |||
325 | |||
290 | /* Ignore any prefix, eg. v850 prepends _ */ | 326 | /* Ignore any prefix, eg. v850 prepends _ */ |
291 | static inline int sym_is(const char *symbol, const char *name) | 327 | static inline int sym_is(const char *symbol, const char *name) |
292 | { | 328 | { |
@@ -362,6 +398,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
362 | else if (sym_is(symname, "__mod_pnp_card_device_table")) | 398 | else if (sym_is(symname, "__mod_pnp_card_device_table")) |
363 | do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id), | 399 | do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id), |
364 | do_pnp_card_entry, mod); | 400 | do_pnp_card_entry, mod); |
401 | else if (sym_is(symname, "__mod_pcmcia_device_table")) | ||
402 | do_table(symval, sym->st_size, sizeof(struct pcmcia_device_id), | ||
403 | do_pcmcia_entry, mod); | ||
365 | } | 404 | } |
366 | 405 | ||
367 | /* Now add out buffered information to the generated C source */ | 406 | /* Now add out buffered information to the generated C source */ |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index f72c81cc9952..2d4f8e28478b 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -380,13 +380,20 @@ static int pdacf_event(event_t event, int priority, event_callback_args_t *args) | |||
380 | /* | 380 | /* |
381 | * Module entry points | 381 | * Module entry points |
382 | */ | 382 | */ |
383 | static struct pcmcia_device_id snd_pdacf_ids[] = { | ||
384 | PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), | ||
385 | PCMCIA_DEVICE_NULL | ||
386 | }; | ||
387 | MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); | ||
388 | |||
383 | static struct pcmcia_driver pdacf_cs_driver = { | 389 | static struct pcmcia_driver pdacf_cs_driver = { |
384 | .owner = THIS_MODULE, | 390 | .owner = THIS_MODULE, |
385 | .drv = { | 391 | .drv = { |
386 | .name = "snd-pdaudiocf", | 392 | .name = "snd-pdaudiocf", |
387 | }, | 393 | }, |
388 | .attach = snd_pdacf_attach, | 394 | .attach = snd_pdacf_attach, |
389 | .detach = snd_pdacf_detach | 395 | .detach = snd_pdacf_detach, |
396 | .id_table = snd_pdacf_ids, | ||
390 | }; | 397 | }; |
391 | 398 | ||
392 | static int __init init_pdacf(void) | 399 | static int __init init_pdacf(void) |
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index fce2ad04fd8b..5f4c13264159 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -18,17 +18,6 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | ||
22 | please add the following as /etc/pcmcia/vxpocket.conf: | ||
23 | |||
24 | device "snd-vxpocket" | ||
25 | class "audio" module "snd-vxpocket" | ||
26 | |||
27 | card "Digigram VX-POCKET" | ||
28 | manfid 0x01f1, 0x0100 | ||
29 | bind "snd-vxpocket" | ||
30 | |||
31 | */ | ||
32 | 21 | ||
33 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
34 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -140,13 +129,20 @@ static void vxp_detach(dev_link_t *link) | |||
140 | * Module entry points | 129 | * Module entry points |
141 | */ | 130 | */ |
142 | 131 | ||
132 | static struct pcmcia_device_id vxp_ids[] = { | ||
133 | PCMCIA_DEVICE_MANF_CARD(0x01f1, 0x0100), | ||
134 | PCMCIA_DEVICE_NULL | ||
135 | }; | ||
136 | MODULE_DEVICE_TABLE(pcmcia, vxp_ids); | ||
137 | |||
143 | static struct pcmcia_driver vxp_cs_driver = { | 138 | static struct pcmcia_driver vxp_cs_driver = { |
144 | .owner = THIS_MODULE, | 139 | .owner = THIS_MODULE, |
145 | .drv = { | 140 | .drv = { |
146 | .name = DEV_INFO, | 141 | .name = DEV_INFO, |
147 | }, | 142 | }, |
148 | .attach = vxp_attach, | 143 | .attach = vxp_attach, |
149 | .detach = vxp_detach | 144 | .detach = vxp_detach, |
145 | .id_table = vxp_ids, | ||
150 | }; | 146 | }; |
151 | 147 | ||
152 | static int __init init_vxpocket(void) | 148 | static int __init init_vxpocket(void) |